teuton 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. checksums.yaml +7 -0
  2. data/bin/teuton +4 -0
  3. data/lib/teuton/application.rb +53 -0
  4. data/lib/teuton/case_manager/case/builtin/main.rb +24 -0
  5. data/lib/teuton/case_manager/case/builtin/package.rb +20 -0
  6. data/lib/teuton/case_manager/case/builtin/service.rb +32 -0
  7. data/lib/teuton/case_manager/case/builtin/user.rb +20 -0
  8. data/lib/teuton/case_manager/case/case.rb +114 -0
  9. data/lib/teuton/case_manager/case/close.rb +29 -0
  10. data/lib/teuton/case_manager/case/config.rb +76 -0
  11. data/lib/teuton/case_manager/case/dsl/check.rb +24 -0
  12. data/lib/teuton/case_manager/case/dsl/deprecated.rb +14 -0
  13. data/lib/teuton/case_manager/case/dsl/expect.rb +78 -0
  14. data/lib/teuton/case_manager/case/dsl/getset.rb +22 -0
  15. data/lib/teuton/case_manager/case/dsl/goto.rb +35 -0
  16. data/lib/teuton/case_manager/case/dsl/log.rb +14 -0
  17. data/lib/teuton/case_manager/case/dsl/main.rb +11 -0
  18. data/lib/teuton/case_manager/case/dsl/missing.rb +12 -0
  19. data/lib/teuton/case_manager/case/dsl/send.rb +69 -0
  20. data/lib/teuton/case_manager/case/dsl/target.rb +16 -0
  21. data/lib/teuton/case_manager/case/dsl/unique.rb +11 -0
  22. data/lib/teuton/case_manager/case/main.rb +7 -0
  23. data/lib/teuton/case_manager/case/play.rb +59 -0
  24. data/lib/teuton/case_manager/case/result/ext_array.rb +43 -0
  25. data/lib/teuton/case_manager/case/result/ext_compare.rb +147 -0
  26. data/lib/teuton/case_manager/case/result/ext_filter.rb +68 -0
  27. data/lib/teuton/case_manager/case/result/result.rb +73 -0
  28. data/lib/teuton/case_manager/case/runner.rb +134 -0
  29. data/lib/teuton/case_manager/case_manager.rb +76 -0
  30. data/lib/teuton/case_manager/check_cases.rb +73 -0
  31. data/lib/teuton/case_manager/dsl.rb +31 -0
  32. data/lib/teuton/case_manager/export_manager.rb +20 -0
  33. data/lib/teuton/case_manager/hall_of_fame.rb +28 -0
  34. data/lib/teuton/case_manager/main.rb +6 -0
  35. data/lib/teuton/case_manager/report.rb +52 -0
  36. data/lib/teuton/case_manager/show.rb +19 -0
  37. data/lib/teuton/case_manager/utils.rb +57 -0
  38. data/lib/teuton/command/create.rb +20 -0
  39. data/lib/teuton/command/download.rb +26 -0
  40. data/lib/teuton/command/main.rb +9 -0
  41. data/lib/teuton/command/play.rb +34 -0
  42. data/lib/teuton/command/readme.rb +23 -0
  43. data/lib/teuton/command/test.rb +35 -0
  44. data/lib/teuton/command/update.rb +27 -0
  45. data/lib/teuton/command/version.rb +13 -0
  46. data/lib/teuton/files/start.rb +13 -0
  47. data/lib/teuton/project/configfile_reader.rb +49 -0
  48. data/lib/teuton/project/laboratory/builtin.rb +23 -0
  49. data/lib/teuton/project/laboratory/dsl.rb +117 -0
  50. data/lib/teuton/project/laboratory/laboratory.rb +55 -0
  51. data/lib/teuton/project/laboratory/show.rb +161 -0
  52. data/lib/teuton/project/name_file_finder.rb +129 -0
  53. data/lib/teuton/project/project.rb +62 -0
  54. data/lib/teuton/project/project_creator.rb +79 -0
  55. data/lib/teuton/project/readme/dsl.rb +109 -0
  56. data/lib/teuton/project/readme/lang.rb +30 -0
  57. data/lib/teuton/project/readme/readme.rb +156 -0
  58. data/lib/teuton/rake_function/check.rb +39 -0
  59. data/lib/teuton/rake_function/install.rb +36 -0
  60. data/lib/teuton/report/close.rb +34 -0
  61. data/lib/teuton/report/formatter/array_formatter.rb +84 -0
  62. data/lib/teuton/report/formatter/base_formatter.rb +33 -0
  63. data/lib/teuton/report/formatter/csv_formatter.rb +31 -0
  64. data/lib/teuton/report/formatter/formatter_factory.rb +73 -0
  65. data/lib/teuton/report/formatter/html_formatter.rb +81 -0
  66. data/lib/teuton/report/formatter/json_formatter.rb +17 -0
  67. data/lib/teuton/report/formatter/list_formatter.rb +71 -0
  68. data/lib/teuton/report/formatter/moodle_csv_formatter.rb +28 -0
  69. data/lib/teuton/report/formatter/resume_array_formatter.rb +49 -0
  70. data/lib/teuton/report/formatter/resume_json_formatter.rb +16 -0
  71. data/lib/teuton/report/formatter/resume_list_formatter.rb +62 -0
  72. data/lib/teuton/report/formatter/resume_txt_formatter.rb +102 -0
  73. data/lib/teuton/report/formatter/resume_yaml_formatter.rb +16 -0
  74. data/lib/teuton/report/formatter/txt_formatter.rb +102 -0
  75. data/lib/teuton/report/formatter/xml_formatter.rb +42 -0
  76. data/lib/teuton/report/formatter/yaml_formatter.rb +18 -0
  77. data/lib/teuton/report/report.rb +55 -0
  78. data/lib/teuton/report/show.rb +111 -0
  79. data/lib/teuton/utils/verbose.rb +15 -0
  80. data/lib/teuton.rb +17 -0
  81. metadata +263 -0
@@ -0,0 +1,31 @@
1
+ require_relative '../application'
2
+ require_relative 'case_manager'
3
+
4
+ def use(filename)
5
+ filename += '.rb'
6
+ app = Application.instance
7
+ rbfiles = File.join(app.project_path, "**", filename)
8
+ files = Dir.glob(rbfiles)
9
+ findfiles = []
10
+ files.sort.each { |f| findfiles << f if f.include?(filename) }
11
+ require_relative findfiles.first
12
+ app.uses << File.basename(findfiles.first)
13
+ end
14
+
15
+ def define_check(name, *args, &block)
16
+ Application.instance.checks[name] = { args: args, block: block }
17
+ end
18
+ alias definecheck define_check
19
+ alias def_check define_check
20
+ alias defcheck define_check
21
+ alias dcheck define_check
22
+
23
+ def group(name, &block)
24
+ Application.instance.groups << { name: name, block: block }
25
+ end
26
+ alias task group
27
+
28
+ def play(&block)
29
+ CaseManager.instance.play(&block)
30
+ end
31
+ alias start play
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../application'
4
+
5
+ # ExportManager#run
6
+ module ExportManager
7
+ def self.run(main_report, cases, args)
8
+ # default :mode=>:all, :format=>:txt
9
+ format = args[:format] || Application.instance.default[:format]
10
+ mode = args[:mode] || :all
11
+ # Export case reports
12
+ if %i[details all].include? mode
13
+ threads = []
14
+ cases.each { |c| threads << Thread.new { c.export format } }
15
+ threads.each(&:join)
16
+ end
17
+ # Export resume report
18
+ main_report.export_resume format if %i[resume all].include? mode
19
+ end
20
+ end
@@ -0,0 +1,28 @@
1
+
2
+ require_relative '../application'
3
+
4
+ class CaseManager
5
+
6
+ private
7
+
8
+ def build_hall_of_fame
9
+ celebrities = {}
10
+
11
+ @cases.each do |c|
12
+ grade = c.grade # report.tail[:grade]
13
+ if celebrities[grade]
14
+ label = celebrities[grade] + '*'
15
+ else
16
+ label = '*'
17
+ end
18
+ celebrities[grade] = label unless c.skip
19
+ end
20
+
21
+ a = celebrities.sort_by { |key, _value| key }
22
+ list = a.reverse
23
+
24
+ app = Application.instance
25
+ app.options[:case_number] = @cases.size
26
+ app.hall_of_fame = list
27
+ end
28
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'check_cases'
4
+ require_relative 'hall_of_fame'
5
+ require_relative 'report'
6
+ require_relative 'show'
@@ -0,0 +1,52 @@
1
+
2
+ class CaseManager
3
+
4
+ private
5
+
6
+ def open_main_report(p_config_filename)
7
+ app = Application.instance
8
+
9
+ @report.head[:tt_title] = "Executing [#{app.name}] (version #{Application::VERSION})"
10
+ @report.head[:tt_scriptname] = app.script_path
11
+ @report.head[:tt_configfile] = p_config_filename
12
+ @report.head[:tt_debug] = true if @debug
13
+ # @report.head[:tt_uses] = app.uses.join(', ')
14
+ @report.head.merge!(app.global)
15
+
16
+ verboseln ' '
17
+ verboseln '=' * @report.head[:tt_title].length
18
+ verboseln @report.head[:tt_title]
19
+ end
20
+
21
+ def close_main_report(start_time)
22
+ finish_time = Time.now
23
+ @report.tail[:start_time] = start_time
24
+ @report.tail[:finish_time] = finish_time
25
+ @report.tail[:duration] = finish_time - start_time
26
+
27
+ verbose "\n[INFO] Duration = #{format('%3.3f',(finish_time - start_time))}"
28
+ verboseln " (#{finish_time})"
29
+ verboseln '=' * @report.head[:tt_title].length
30
+ verboseln ' '
31
+
32
+ app = Application.instance
33
+ @cases.each do |c|
34
+ line = {}
35
+ if c.skip?
36
+ line = { skip: true, id: '-', grade: 0.0, letter: '',
37
+ members: '-', conn_status: {},
38
+ moodle_id: '', moodle_feedback: '' }
39
+ else
40
+ line[:skip] = false
41
+ line[:id] = format('case_%02d', c.id.to_i)
42
+ line[:letter] = app.letter[:error] if c.grade < 50.0
43
+ line[:grade] = c.grade.to_f #format(' %3d', c.grade.to_f)
44
+ line[:members] = c.members
45
+ line[:conn_status] = c.conn_status
46
+ line[:moodle_id] = c.get(:tt_moodle_id)
47
+ line[:moodle_feedback] = "\"Filename: #{c.filename}. Date: #{Time.now}\""
48
+ end
49
+ @report.lines << line
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+ require_relative '../application'
3
+
4
+ # CaseManager#show
5
+ class CaseManager
6
+ def show(mode = :resume)
7
+ return if Application.instance.quiet?
8
+
9
+ @report.show if %i[resume all].include? mode
10
+
11
+ return unless %i[details all].include? mode
12
+
13
+ @cases.each do |c|
14
+ puts '____'
15
+ c.show
16
+ end
17
+ puts '.'
18
+ end
19
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../application'
4
+
5
+ # Define general use methods
6
+ module Utils
7
+ # Create the directory if it dosn't exist.
8
+ def ensure_dir(dirname)
9
+ unless Dir.exist?(dirname)
10
+ FileUtils.mkdir_p(dirname)
11
+ return false
12
+ end
13
+ true
14
+ end
15
+
16
+ def encode_and_split(encoding, text)
17
+ # Convert text to UTF-8 deleting unknown chars
18
+ text = text || '' # Ensure text is not nil
19
+ flag = [:default, 'UTF-8'].include? encoding
20
+ return text.encode('UTF-8', invalid: :replace).split("\n") if flag
21
+
22
+ # Convert text from input ENCODING to UTF-8
23
+ ec = Encoding::Converter.new(encoding.to_s, 'UTF-8')
24
+ begin
25
+ text = ec.convert(text)
26
+ rescue StandardError => e
27
+ puts "[ERROR] #{e}: Declare text encoding..."
28
+ puts " goto :host, :exec => 'command', :encoding => 'ISO-8859-1'"
29
+ end
30
+
31
+ text.split("\n")
32
+ end
33
+
34
+ def my_execute(cmd, encoding = 'UTF-8')
35
+ return { exitstatus: 0, content: '' } if Application.instance.debug
36
+
37
+ begin
38
+ text = `#{cmd}`
39
+ exitstatus = $CHILD_STATUS.exitstatus
40
+ rescue StandardError => e # rescue Exception => e
41
+ verbose '!'
42
+ puts("[ERROR] #{e}: Local exec: #{cmd}")
43
+ end
44
+ content = encode_and_split(encoding, text)
45
+ { exitstatus: exitstatus, content: content }
46
+ end
47
+
48
+ def verboseln(text)
49
+ verbose(text + "\n")
50
+ end
51
+
52
+ def verbose(text)
53
+ return if Application.instance.quiet?
54
+
55
+ print text
56
+ end
57
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../project/project_creator.rb'
4
+
5
+ # Teuton#create
6
+ class Teuton < Thor
7
+ map ['c', '-c', '--create'] => 'create'
8
+ desc 'create DIRECTORY', 'Create skeleton for a new project'
9
+ long_desc <<-LONGDESC
10
+ Create files for a new project: foo.rb, foo.yaml and .gitignore
11
+
12
+ Example:
13
+
14
+ #{$PROGRAM_NAME} create foo/demo
15
+
16
+ LONGDESC
17
+ def create(path_to_new_dir)
18
+ ProjectCreator.create(path_to_new_dir)
19
+ end
20
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rainbow'
4
+
5
+ # Class method Teuton#download
6
+ class Teuton < Thor
7
+ map ['-dc', '--dc', '--download'] => 'download'
8
+ desc 'download', 'Download Teuton challenges from git repo'
9
+ long_desc <<-LONGDESC
10
+ - Download Teuton challenges from git repo.
11
+
12
+ - Same as:
13
+ git clone https://github.com/teuton-software/teuton-challenges.git
14
+
15
+ Example:
16
+
17
+ #{$PROGRAM_NAME} download
18
+
19
+ LONGDESC
20
+ def download
21
+ repo = 'teuton-challenges'
22
+ puts "[INFO] Downloading <#{repo}> repo..."
23
+ system("git clone https://github.com/teuton-software/#{repo}.git")
24
+ puts "[INFO] Your files are into <#{Rainbow(repo).bright}> directory..."
25
+ end
26
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'create'
4
+ require_relative 'download'
5
+ require_relative 'play'
6
+ require_relative 'readme'
7
+ require_relative 'test'
8
+ require_relative 'update'
9
+ require_relative 'version'
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Teuton#play
4
+ class Teuton < Thor
5
+ map ['p', '-p', 'play', '--play'] => 'play'
6
+ option :export, type: :string
7
+ option :cname, type: :string
8
+ option :cpath, type: :string
9
+ option :case, type: :string
10
+ option :quiet, type: :boolean
11
+ desc '[play] [OPTIONS] DIRECTORY',
12
+ 'Run challenge from directory'
13
+ long_desc <<-LONGDESC
14
+ This function execute challenge from specified directory.
15
+ By default, show progress on the screen.
16
+
17
+ Let's see others options:
18
+
19
+ (1) teuton foo, run challenge from foo/start.rb with foo/config.yaml config file.
20
+
21
+ (2) teuton play foo, same as (1).
22
+
23
+ (3) teuton play --export=json foo, run challenge and export using json format.
24
+ Others output formats availables are: txt, colored_text, json, yaml.
25
+
26
+ (4) teuton play --cname=demo foo, run challenge from foo/start.rb with foo/demo.yaml config file.
27
+
28
+ (5) teuton foo/demo.rb, Run challenge from foo/demo.rb with foo/demo.yaml config file.
29
+
30
+ LONGDESC
31
+ def play(path_to_rb_file)
32
+ Project.play(path_to_rb_file, options)
33
+ end
34
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Teuton#readme
4
+ class Teuton < Thor
5
+ map ['r', '-r', '--readme'] => 'readme'
6
+ option :lang, type: :string
7
+ desc 'readme DIRECTORY',
8
+ 'Create README.md file from challenge contents'
9
+ long_desc <<-LONGDESC
10
+
11
+ (1) teuton readme foo
12
+ , Create README.md from foo/start.rb.
13
+
14
+ (2) teuton readme foo/demo.rb
15
+ , Create README.md from foo/demo.rb.
16
+
17
+ By default lang=es, but It's available lang=en too.
18
+
19
+ LONGDESC
20
+ def readme(path_to_rb_file)
21
+ Project.readme(path_to_rb_file, options)
22
+ end
23
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Teuton#test
4
+ class Teuton < Thor
5
+ map ['t', '-t', '--test'] => 'test'
6
+ option :c, type: :boolean
7
+ option :cname, type: :string
8
+ option :cpath, type: :string
9
+ desc 'test [OPTIONS] DIRECTORY',
10
+ 'Test or check challenge contents'
11
+ long_desc <<-LONGDESC
12
+
13
+ (1) teuton test path/to/dir/foo
14
+ , Test content of start.rb and config.yaml files.
15
+
16
+ (2) teuton test path/to/dir/foo -c
17
+ , Only test CONFIG information from config.yaml.
18
+
19
+ (3) teuton test path/to/dir/foo --cname=demo
20
+ , Test content of start.rb and demo.yaml files.
21
+
22
+ (4) teuton test path/to/file/foo.rb
23
+ , Test content of foo.rb and foo.yaml files.
24
+
25
+ (5) teuton test path/to/file/foo.rb -c
26
+ , Only test CONFIG information from foo.yaml.
27
+
28
+ (6) teuton test path/to/file/foo.rb --cname=demo
29
+ , Test content of foo.rb and demo.yaml files.
30
+
31
+ LONGDESC
32
+ def test(path_to_rb_file)
33
+ Project.test(path_to_rb_file, options)
34
+ end
35
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rainbow'
4
+
5
+ # Class method Teuton#update
6
+ class Teuton < Thor
7
+ map ['--update', '-u', 'u'] => 'update'
8
+ desc 'update', 'Update TEUTON from git repo'
9
+ long_desc <<-LONGDESC
10
+ Update TEUTON project, downloading files from git repo.
11
+ Execute "cd PATH/TO/TEUTON/DIR && git pull".
12
+
13
+ Alias: teuton u, teuton -u, teuton --update
14
+
15
+ LONGDESC
16
+ def update
17
+ dir = File.absolute_path(File.join(File.dirname(__FILE__), '..', '..'))
18
+ ok = system("cd #{dir} && git pull")
19
+ if ok
20
+ puts Rainbow('[ OK ] teuton update').green.bright
21
+ exit(0)
22
+ else
23
+ puts Rainbow('[FAIL] teuton update').red.bright
24
+ exit(1)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rainbow'
4
+
5
+ # Class method Teuton#version
6
+ class Teuton < Thor
7
+ map ['v', '-v', '--version'] => 'version'
8
+ desc 'version', 'Show the program version'
9
+ def version
10
+ print Rainbow(Application::NAME).bright.blue
11
+ puts ' (version ' + Rainbow(Application::VERSION).green + ')'
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+
2
+ group "GROUP NAME" do
3
+
4
+ target "TARGET-1 DESCRIPTION"
5
+ goto :localhost, :exec => "COMMAND-1"
6
+ expect "TEXT-1"
7
+
8
+ end
9
+
10
+ play do
11
+ show
12
+ export
13
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml'
4
+ require 'json'
5
+
6
+ # Functions that read data from ConfigFile using formats YAML and JSON
7
+ # * read
8
+ # * read_yaml
9
+ # * read_json
10
+ module ConfigFileReader
11
+ def self.read(filepath)
12
+ unless File.exist?(filepath)
13
+ data = {}
14
+ data[:global] = {}
15
+ data[:alias] = {}
16
+ data[:cases] = [{ tt_members: 'anonymous' }]
17
+ return data
18
+ end
19
+ return read_yaml(filepath) if File.extname(filepath) == '.yaml'
20
+
21
+ return read_json(filepath) if File.extname(filepath) == '.json'
22
+
23
+ raise "[ERROR] ConfigFileReader: #{filepath}"
24
+ end
25
+
26
+ def self.read_yaml(filepath)
27
+ begin
28
+ data = YAML.load(File.open(filepath))
29
+ rescue StandardError => e
30
+ puts "\n" + ('=' * 80)
31
+ puts "[ERROR] ConfigFileReader#read <#{filepath}>"
32
+ puts ' I suggest to revise file format!'
33
+ puts " #{e.message}\n" + ('=' * 80)
34
+ raise "[ERROR] ConfigFileReader <#{e}>"
35
+ end
36
+ data[:global] = data[:global] || {}
37
+ data[:alias] = data[:alias] || {}
38
+ data[:cases] = data[:cases] || []
39
+ data
40
+ end
41
+
42
+ def self.read_json(filepath)
43
+ data = JSON.parse(File.read(filepath), symbolize_names: true)
44
+ data[:global] = data[:global] || {}
45
+ data[:alias] = data[:alias] || {}
46
+ data[:cases] = data[:cases] || []
47
+ data
48
+ end
49
+ end
@@ -0,0 +1,23 @@
1
+
2
+ class Builtin
3
+ attr_accessor :param
4
+
5
+ def initialize(parent)
6
+ @parent = parent
7
+ end
8
+
9
+ def method_missing(method)
10
+ @parent.log "BUILTIN #{method}"
11
+ end
12
+ end
13
+
14
+ # Laboratory
15
+ # * service
16
+ class Laboratory
17
+ def service(param)
18
+ log "BUILTIN service(#{param})"
19
+ @builtin = @builtin || Builtin.new(self)
20
+ @builtin.param = param
21
+ @builtin
22
+ end
23
+ end
@@ -0,0 +1,117 @@
1
+ # Laboratory
2
+ # * target
3
+ # * request (development)
4
+ # * tempfile
5
+ # * goto
6
+ # * run
7
+ # * expect
8
+ # * get
9
+ # * unique
10
+ # * log
11
+ # * set
12
+ class Laboratory
13
+ def readme(_text)
14
+ # Usefull for "teuton reamde" action.
15
+ end
16
+
17
+ def target(desc, args = {})
18
+ @stats[:targets] += 1
19
+ @targetid += 1
20
+ weight = args[:weight] || 1.0
21
+ verboseln '(%03d' % @targetid + ") target #{desc}"
22
+ verboseln " weight #{weight}"
23
+ end
24
+ alias goal target
25
+
26
+ def request(text)
27
+ @requests << text.to_s
28
+ end
29
+
30
+ def tempfile(_tempfile = nil)
31
+ 'tempfile'
32
+ end
33
+
34
+ def goto(host = :localhost, args = {})
35
+ result.reset
36
+
37
+ if @hosts[host]
38
+ @hosts[host] += 1
39
+ else
40
+ @hosts[host] = 1
41
+ end
42
+ verboseln " goto #{host} and #{args}"
43
+ end
44
+
45
+ def run(command, args = {})
46
+ args[:exec] = command
47
+ goto(:localhost, args)
48
+ end
49
+
50
+ def expect(_cond, args = {})
51
+ #unless [ String, Array, Regexp].include? _cond.class
52
+ # verboseln "[ERROR] expect #{_cond} (#{_cond.class})"
53
+ # return
54
+ #end
55
+ verboseln " alter #{result.alterations}" unless result.alterations.empty?
56
+ #verboseln " expect #{result.expected} (#{result.expected.class})"
57
+ verboseln " expect #{_cond} (#{_cond.class})"
58
+ verboseln ''
59
+ end
60
+
61
+ def expect_one(_cond, args = {})
62
+ verboseln " alter #{result.alterations}" unless result.alterations.empty?
63
+ verboseln " expect_one #{_cond} (#{_cond.class})"
64
+ verboseln ''
65
+ end
66
+
67
+ def expect_none(_cond, args = {})
68
+ verboseln " alter #{result.alterations}" unless result.alterations.empty?
69
+ verboseln " expect_none #{_cond} (#{_cond.class})"
70
+ verboseln ''
71
+ end
72
+
73
+ def get(varname)
74
+ @stats[:gets] += 1
75
+
76
+ if @gets[varname]
77
+ @gets[varname] += 1
78
+ else
79
+ @gets[varname] = 1
80
+ end
81
+
82
+ "get(#{varname})"
83
+ end
84
+
85
+ # If a method call is missing, then delegate to concept parent.
86
+ def method_missing(method)
87
+ a = method.to_s
88
+ instance_eval("get(:#{a[0, a.size - 1]})") if a[a.size - 1] == '?'
89
+ end
90
+
91
+ def gett(option)
92
+ value = get(option)
93
+ value
94
+ end
95
+
96
+ def unique(key, _value)
97
+ @stats[:uniques] += 1
98
+
99
+ verboseln " ! Unique value for <#{key}>"
100
+ verboseln ''
101
+ end
102
+
103
+ def log(text = '', type = :info)
104
+ @stats[:logs] += 1
105
+ verboseln " log [#{type}]: " + text.to_s
106
+ end
107
+
108
+ def set(key, value)
109
+ @stats[:sets] += 1
110
+
111
+ key = ':' + key.to_s if key.class == Symbol
112
+ value = ':' + value.to_s if value.class == Symbol
113
+
114
+ @sets[key] = value
115
+ "set(#{key},#{value})"
116
+ end
117
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'terminal-table'
4
+ require 'rainbow'
5
+
6
+ require_relative '../../application'
7
+ require_relative '../../case_manager/case/result/result'
8
+ require_relative 'show'
9
+ require_relative 'dsl'
10
+ require_relative 'builtin'
11
+
12
+ def use(filename)
13
+ filename += '.rb'
14
+ app = Application.instance
15
+ rbfiles = File.join(app.project_path, "**", filename)
16
+ files = Dir.glob(rbfiles)
17
+ use = []
18
+ files.sort.each { |f| use << f if f.include?(filename) }
19
+ require_relative use[0]
20
+ end
21
+
22
+ def group(name, &block)
23
+ Application.instance.groups << { name: name, block: block }
24
+ end
25
+ alias task group
26
+
27
+ def start(&block)
28
+ # don't do nothing
29
+ end
30
+ alias play start
31
+
32
+ # Show objectives stats from RB script file
33
+ class Laboratory
34
+ attr_reader :result
35
+
36
+ def initialize(script_path, config_path)
37
+ @path = {}
38
+ @path[:script] = script_path
39
+ @path[:dirname] = File.dirname(script_path)
40
+ @path[:filename] = File.basename(script_path, '.rb')
41
+ @path[:config] = config_path
42
+ reset
43
+ end
44
+
45
+ def reset
46
+ @result = Result.new
47
+ @targetid = 0
48
+ @stats = { groups: 0, targets: 0, uniques: 0, gets: 0, logs: 0, sets: 0 }
49
+ @gets = {}
50
+ @sets = {}
51
+ @hosts = {}
52
+ @requests = []
53
+ @verbose = Application.instance.verbose
54
+ end
55
+ end