class MxxRu::TextfileUnittestTarget

The class of a target, which is binary unit-test application, which create one or many text files.

Given target performs a build of application, and then runs it and compares results with files which contains correct results.

The basic idea consists in the presence of project file, which controls the build of unit-test application. In that project file, target object is created, inherited from MxxRu::BinaryTarget. To start unit-test it's necessary to create one more file, where target object of MxxRu::TextfileUnittestTarget class is created. For example:

Unit-test application build file:

MxxRu::setup_target(
  MxxRu::Cpp::ExeTarget.new( "test/pack/prj.rb" ) {
    ...
  }
)

File to run unit-test:

MxxRu::setup_target(
  MxxRu::TextfileUnittestTarget.new( 
    "test/pack/pack.ut.rb",
    "test/pack/prj.rb" ) {

    launch( "--loops 16 --out test/pack/out/16.txt",
      [ pair( "test/pack/out/16.txt",
          "test/pack/out/etalon/16.txt" ) ] )

    launch( "--loops 32 --out test/pack/out/32.txt",
      [ pair( "test/pack/out/32.txt",
          "test/pack/out/etalon/32.txt" ) ] )
  }
)

File which is using that unit-test.

MxxRu::setup_target(
  MxxRu::Cpp::CompositeTarget.new( MxxRu::BUILD_ROOT ) {
    required_prj( "some/project/prj.rb" )
    required_prj( "test/pack/prj.ut.rb" )
  }
)

Constants

File_mismatch_ex

Exception, thrown if files are not equal.

Must_be_one_target_name_ex

Exception, thrown if one subordinated project generated more than one result name.

Attributes

mxx_build_state[R]

True if build method was already executed.

mxx_launches[R]

Description of test application runs. Array of Launch.

mxx_target_project[R]

Target, responsible for build of unit-test application.

Public Class Methods

new( a_alias, a_target_project, &block ) click to toggle source

Constructor.

a_alias

Self alias.

a_target_project

Project, responsible for build of unit-test application.

Calls superclass method MxxRu::AbstractTarget::new
# File lib/mxx_ru/textfile_unittest.rb, line 158
def initialize( a_alias, a_target_project, &block )
  super( a_alias )

  @mxx_build_state = nil

  @mxx_target_project = required_prj( a_target_project )

  @mxx_launches = Array.new

  instance_eval( &block ) if block
end

Public Instance Methods

build() click to toggle source

Build subordinated project and run it.

If unit-test application returns exit code not equal to 0, exception is thrown.

# File lib/mxx_ru/textfile_unittest.rb, line 196
def build
  if !@mxx_build_state
    @mxx_target_project.build

    # Determining the name of application, which should be run.
    full_names = @mxx_target_project.mxx_full_targets_names
    if 1 != full_names.size
      raise MustBeOneTargetNameEx.new( full_names )
    end

    # No execution of commands in dry-run mode.
    if !MxxRu::Util::Mode.instance.is_dry_run
      puts "running unit test: #{full_names[0]}..."
      do_all_launches( full_names[ 0 ] )
    end

    @mxx_build_state = TargetState.new( TargetState::REBUILT )
  end

  return @mxx_build_state
end
clean() click to toggle source

Cleanup the project.

Executes clean method from subordinated project. Deletes all files, defined as result files of unit-test application.

# File lib/mxx_ru/textfile_unittest.rb, line 222
def clean
  @mxx_target_project.clean

  @mxx_launches.each { |launch|
    launch.pairs.each { |pair|
      Util.delete_file( pair.produced )
    }
  }
end
launch( a_cmdline, a_pairs ) click to toggle source

Add description of sequental run of test application.

a_cmdline

Command line parameters. May be empty string of nil if no parameters required.

a_pairs

A list of pairs of file names to compare. Should be Array of values returned by pair() method.

Comparation will be performed in order they are defined in a_pairs. Comparation is interrupted on first mismatch.

# File lib/mxx_ru/textfile_unittest.rb, line 187
def launch( a_cmdline, a_pairs )
  a_cmdline = "" if !a_cmdline
  @mxx_launches << Launch.new( a_cmdline, a_pairs )
end
pair( a_produced, a_etalon ) click to toggle source

Create description of file pairs to compare.

a_produced

Name of generated file.

a_etalon

Name of correct file.

# File lib/mxx_ru/textfile_unittest.rb, line 174
def pair( a_produced, a_etalon )
  return Pair.new( a_produced, a_etalon )
end
reset() click to toggle source

Reset build status.

# File lib/mxx_ru/textfile_unittest.rb, line 233
def reset
  @mxx_target_project.reset
  @mxx_build_state = nil
end

Protected Instance Methods

do_all_launches( a_file_to_exec ) click to toggle source

Perform all defined runs of test application. This method should not be executed in dry-run mode.

# File lib/mxx_ru/textfile_unittest.rb, line 241
def do_all_launches( a_file_to_exec )
  # On mswin32 platform if file name is in unix format and
  # redirection of input/output is set, some problems with
  # execution would occur.
  native_file_name = Util::native_pathname( a_file_to_exec )

  @mxx_launches.each { |launch|
    cmdline = native_file_name + " " + launch.cmdline 
    puts "\tlaunching '#{cmdline}'..."
    if !system( cmdline )
      puts "\n\nunit test '#{cmdline}' FAILED! #{$?}"
      raise BuildEx.new( cmdline, $? )
    end

    # Execution of application was successful.
    # Let's compare files.
    launch.pairs.each { |pair|
      puts "\t\tcomparing '#{pair.produced}' and '#{pair.etalon}'"
      do_file_compare( cmdline, pair.produced, pair.etalon )
    }
  }
end
do_file_compare( a_cmdline, a_produced, a_etalon ) click to toggle source

Perform comparation of two files. If they are not identical, FileMismatchEx exception is thrown. If some system exceptions would occur (absence of file for example), BuildEx ewxception will be thrown.

# File lib/mxx_ru/textfile_unittest.rb, line 268
def do_file_compare( a_cmdline, a_produced, a_etalon )
  begin
    produced_file = File.new( a_produced, "r" )
    etalon_file = File.new( a_etalon, "r" )

    line_num = 1
    while true
      l1 = produced_file.gets
                l1.chop! if l1
      l2 = etalon_file.gets
                l2.chop! if l2

      if l1 != l2
        raise FileMismatchEx.new( a_cmdline,
          a_produced, a_etalon, line_num,
          l1, l2 )
      else
        line_num += 1
        if !l1
          break
        end
      end
    end

  rescue Exception => ex
    raise BuildEx.new( a_cmdline,
      "Error during comparing files " +
      "'#{a_produced}', '#{a_etalon}': #{ex}" )
  end
end