teuton 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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