teuton 2.1.10 → 2.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +15 -12
  3. data/bin/check_teuton +0 -2
  4. data/docs/changelog/ideas.md +132 -0
  5. data/docs/changelog/v2.1.md +14 -122
  6. data/docs/changelog/v2.2.md +52 -28
  7. data/docs/changelog/version2.1.md +4 -0
  8. data/docs/commands/README.md +58 -15
  9. data/docs/commands/example_check.md +0 -4
  10. data/docs/commands/example_run.md +0 -4
  11. data/docs/dsl/README.md +1 -1
  12. data/docs/dsl/definition/result.md +1 -0
  13. data/docs/dsl/definition/run_remote.md +12 -6
  14. data/docs/dsl/definition/target.md +9 -10
  15. data/docs/dsl/execution/export.md +27 -20
  16. data/docs/install/README.md +13 -18
  17. data/docs/install/vagrant_docker.md +1 -1
  18. data/docs/learn/README.md +8 -8
  19. data/docs/learn/example-01-target.md +25 -25
  20. data/docs/learn/example-02-config.md +38 -49
  21. data/docs/learn/example-03-remote-hosts.md +22 -22
  22. data/docs/learn/{example-11-first-test.md → example-04-new-test.md} +23 -24
  23. data/docs/learn/{example-04-use.md → example-05-use.md} +6 -6
  24. data/docs/learn/{example-05-debug.md → example-06-debug.md} +8 -8
  25. data/docs/learn/{example-06-log.md → example-07-log.md} +7 -7
  26. data/docs/learn/example-08-readme.md +59 -0
  27. data/docs/learn/example-09-preserve.md +41 -0
  28. data/docs/videos.md +19 -0
  29. data/lib/teuton/application.rb +22 -3
  30. data/lib/teuton/case_manager/case/builtin/main.rb +3 -19
  31. data/lib/teuton/case_manager/case/builtin/package.rb +7 -6
  32. data/lib/teuton/case_manager/case/builtin/service.rb +9 -8
  33. data/lib/teuton/case_manager/case/builtin/teuton_file.rb +28 -0
  34. data/lib/teuton/case_manager/case/builtin/teuton_host.rb +31 -0
  35. data/lib/teuton/case_manager/case/builtin/user.rb +8 -7
  36. data/lib/teuton/case_manager/case/case.rb +1 -1
  37. data/lib/teuton/case_manager/case/dsl/goto.rb +2 -2
  38. data/lib/teuton/case_manager/case/dsl/log.rb +1 -1
  39. data/lib/teuton/case_manager/case/dsl/macro.rb +4 -1
  40. data/lib/teuton/case_manager/case/dsl/send.rb +2 -1
  41. data/lib/teuton/case_manager/case/play.rb +2 -0
  42. data/lib/teuton/case_manager/case/result/ext_compare.rb +16 -0
  43. data/lib/teuton/case_manager/case/result/result.rb +1 -1
  44. data/lib/teuton/case_manager/case/runner.rb +30 -4
  45. data/lib/teuton/case_manager/case_manager.rb +1 -1
  46. data/lib/teuton/case_manager/dsl.rb +10 -0
  47. data/lib/teuton/case_manager/export_manager.rb +24 -5
  48. data/lib/teuton/case_manager/utils.rb +1 -1
  49. data/lib/teuton/{project/laboratory → check}/builtin.rb +0 -0
  50. data/lib/teuton/{project/laboratory → check}/dsl.rb +40 -28
  51. data/lib/teuton/{project/laboratory → check}/laboratory.rb +3 -8
  52. data/lib/teuton/{project/laboratory → check}/show.rb +53 -59
  53. data/lib/teuton/cli.rb +85 -14
  54. data/lib/teuton/{project/readme → readme}/dsl.rb +0 -0
  55. data/lib/teuton/{project/readme → readme}/lang.rb +1 -1
  56. data/lib/teuton/{project/readme → readme}/readme.rb +22 -18
  57. data/lib/teuton/report/formatter/array_formatter.rb +13 -1
  58. data/lib/teuton/report/formatter/base_formatter.rb +18 -5
  59. data/lib/teuton/{project/skeleton.rb → skeleton.rb} +7 -18
  60. data/lib/teuton/utils/configfile_reader.rb +121 -0
  61. data/lib/teuton/{project → utils}/name_file_finder.rb +46 -26
  62. data/lib/teuton/version.rb +8 -0
  63. data/lib/teuton.rb +39 -32
  64. metadata +109 -62
  65. data/lib/teuton/case_manager/case/dsl/deprecated.rb +0 -14
  66. data/lib/teuton/cli/check.rb +0 -38
  67. data/lib/teuton/cli/main.rb +0 -6
  68. data/lib/teuton/cli/play.rb +0 -38
  69. data/lib/teuton/cli/readme.rb +0 -26
  70. data/lib/teuton/cli/version.rb +0 -12
  71. data/lib/teuton/files/gitignore +0 -2
  72. data/lib/teuton/project/configfile_reader.rb +0 -49
  73. data/lib/teuton/project/project.rb +0 -80
@@ -1,14 +1,14 @@
1
1
  [<< back](README.md)
2
2
 
3
- 1. [Definition section](#definition-section)
4
- 2. [Run test](#execution-section)
5
- 3. [Result](#result)
3
+ # Example: learn-07-log
6
4
 
7
- # Example: learn-06-log
5
+ > This example is on GitHub repository at `examples/learn-06-log/`.
8
6
 
9
7
  Let's learn how to create log messages.
10
8
 
11
- > This example is on GitHub repository at `examples/learn-06-log/`.
9
+ 1. [Definition section](#definition-section)
10
+ 2. [Run test](#execution-section)
11
+ 3. [Result](#result)
12
12
 
13
13
  ## Definition section
14
14
 
@@ -29,7 +29,7 @@ end
29
29
 
30
30
  ## Result
31
31
 
32
- **Let's see example**: Content of `var/learn-06-log/case-01.txt` file.
32
+ **Let's see example**: Content of `var/learn-07-log/case-01.txt` file.
33
33
 
34
34
  ```bash
35
35
  CONFIGURATION
@@ -37,7 +37,7 @@ CONFIGURATION
37
37
  | tt_members | anonymous |
38
38
  | tt_sequence | false |
39
39
  | tt_skip | false |
40
- | tt_testname | learn-06-log |
40
+ | tt_testname | learn-07-log |
41
41
  +-------------+--------------+
42
42
 
43
43
  LOGS
@@ -0,0 +1,59 @@
1
+ [<< back](README.md)
2
+
3
+ # Example: learn-07-readme
4
+
5
+ > This example is on GitHub repository at `examples/learn-08-readme/`.
6
+
7
+ Create README files (with test instructions) from our test definition.
8
+
9
+ 1. [Definition section](#definition-section)
10
+ 2. [Execute command](#execute-command)
11
+ 3. [Result](#result)
12
+
13
+ ## Definition section
14
+
15
+ Take a look at our test definition section (Group):
16
+ ```ruby
17
+ group "Customize readme output" do
18
+ readme "This is our README example."
19
+ readme "And here we'll see how to use readme keyword"
20
+
21
+ target "Create user david."
22
+ readme "Help: you can use 'useradd' command to create users."
23
+ readme "Remember: Only root is permitted to create new users."
24
+
25
+ run "id david"
26
+ expect "david"
27
+
28
+ end
29
+ ```
30
+
31
+ > In this example, localhost's OS must be GNU/Linux (any other compatible OS) because the command used is `id david`.
32
+
33
+ There exists some `readme` instructions after `group` and `target` lines.
34
+
35
+ ## Execute command
36
+
37
+ To generate automatically a README file from previous test, execute this:
38
+
39
+ ```
40
+ teuton readme example/learn-08-readme > example/learn-08-readme/README.md
41
+ ```
42
+
43
+ ## Result
44
+
45
+ **Let's see the output**: Content of `example/learn-08-readme/README.md` file.
46
+
47
+ ---
48
+ # learn-08-readme
49
+
50
+ ## Customize readme output
51
+
52
+ This is our README example.
53
+ And here we'll see how to use readme keyword
54
+
55
+ Go to [LOCALHOST](#required-hosts) host, and do next:
56
+ * Create user david.
57
+ * Help: you can use 'useradd' command to create users.
58
+ * Remember: Only root is permitted to create new users.
59
+ ---
@@ -0,0 +1,41 @@
1
+ [<< back](README.md)
2
+
3
+ # Example: learn-09-preserve
4
+
5
+ > This example is on GitHub repository at `examples/learn-09-preserve/`.
6
+
7
+ Older output report files are overwritten with new reports, every time we run teuton test. With `preserve` option we keep copies.
8
+
9
+ 1. [Execution section](#execution-section)
10
+ 2. [Result](#result)
11
+
12
+ ## Execution section
13
+
14
+ Take a look at our test execution section (Play):
15
+ ```ruby
16
+ play do
17
+ show
18
+ export preserve: true
19
+ end
20
+ ```
21
+
22
+ > More information about [export](../dsl/execution/export.md) keyword.
23
+ ## Result
24
+
25
+ Example, executing `teuton run example/learn-09-preserve` twice:
26
+
27
+ ```
28
+ var
29
+ └── learn-09-preserve
30
+ ├── 20200519-113035
31
+ │   ├── case-01.txt
32
+ │   ├── moodle.csv
33
+ │   └── resume.txt
34
+ ├── 20200520-113039
35
+ │   ├── case-01.txt
36
+ │   ├── moodle.csv
37
+ │   └── resume.txt
38
+ ├── case-01.txt
39
+ ├── moodle.csv
40
+ └── resume.txt
41
+ ```
data/docs/videos.md ADDED
@@ -0,0 +1,19 @@
1
+ [<< back](../README.md)
2
+
3
+ # News
4
+
5
+ * [Introducción a Teuton](https://elpuig.xeill.net/Members/vcarceler/articulos/introduccion-a-teuton): iniciarse en el uso de Teutón gracias al fantástico artículo de Víctor Carceler.
6
+ * [Verificar prácticas de GNS3 con Teuton](https://elpuig.xeill.net/Members/juanmorote/articulos/verificar-practicas-de-gns3-con-teuton): GNS3 es un excelente simulador de red Open Source que además se entiende con Teuton a las mil maravillas.
7
+
8
+ # Videos
9
+
10
+ Teuton en el 2016 se llamaba "sysadmingame".
11
+ * [CHAPI16 - Presentación sysadmingame chapi16 - Abril 2016](https://youtu.be/cNJaB5xzHHQ)
12
+ * sysadmingame:
13
+ 1. [Instalación del programa](https://youtu.be/dnyMq9_KDco)
14
+ 2. [Crear un caso simple](https://youtu.be/0e2g5Izvc6c)
15
+ 3. [Crear un caso complejo](https://youtu.be/ebEK6OXH8kQ)
16
+
17
+ Teuton:
18
+ * [Apuntes FP Informática - I Congreso Virtual - Mayo 2020](https://youtu.be/RxIV26BAoGo)
19
+ * [Teuton Software 2.1 - Tutorial - Oct 2020](https://youtu.be/cyBN-rOYQeY)
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'singleton'
4
+ require_relative 'version'
5
+ require_relative 'utils/name_file_finder'
4
6
 
5
7
  # This Singleton contains application params
6
8
  class Application
7
9
  include Singleton
8
-
9
- VERSION = '2.1.10' # Application version
10
- NAME = 'teuton' # Application name
10
+ include Teuton
11
11
 
12
12
  attr_reader :letter
13
13
  attr_reader :running_basedir, :output_basedir
@@ -71,4 +71,23 @@ class Application
71
71
 
72
72
  false
73
73
  end
74
+
75
+ ##
76
+ # Preprocess input options:
77
+ # * Convert input case options String to an Array of integers
78
+ # * Read color input option
79
+ # rubocop:disable Metrics/AbcSize
80
+ def add_input_params(projectpath, options)
81
+ @options.merge! options
82
+ NameFileFinder.find_filenames_for(projectpath)
83
+ @options['color'] = true if @options['color'].nil?
84
+ Rainbow.enabled = @options['color']
85
+ @options['panel'] = false if @options['panel'].nil?
86
+
87
+ return if @options['case'].nil?
88
+
89
+ a = @options['case'].split(',')
90
+ @options['case'] = a.collect!(&:to_i)
91
+ end
92
+ # rubocop:enable Metrics/AbcSize
74
93
  end
@@ -1,24 +1,8 @@
1
1
 
2
- require_relative 'package'
3
- require_relative 'service'
4
- require_relative 'user'
2
+ require_relative 'teuton_host'
5
3
 
6
4
  class Case
7
- def package(param)
8
- @package = @package || Package.new(self)
9
- @package.param = param
10
- @package
11
- end
12
-
13
- def service(param)
14
- @service = @service || Service.new(self)
15
- @service.param = param
16
- @service
17
- end
18
-
19
- def user(param)
20
- @user = @user || User.new(self)
21
- @user.param = param
22
- @user
5
+ def host(host = 'localhost')
6
+ TeutonHost.new(self, host)
23
7
  end
24
8
  end
@@ -1,20 +1,21 @@
1
1
 
2
2
  class Package
3
- attr_accessor :param
4
-
5
- def initialize(parent)
6
- @parent = parent
3
+ def initialize(teuton_host, param)
4
+ @teuton_host = teuton_host
5
+ @parent = teuton_host.parent
6
+ @host = teuton_host.host
7
+ @param = param
7
8
  end
8
9
 
9
10
  def installed?
10
11
  @parent.target("Package #{@param} installed?")
11
- @parent.run "whereis #{@param}"
12
+ @parent.run "whereis #{@param}", on: @host
12
13
  @parent.expect_one [ 'bin', @param ]
13
14
  end
14
15
 
15
16
  def not_installed?
16
17
  @parent.target("Package #{@param} not installed?")
17
- @parent.run "whereis #{@param}"
18
+ @parent.run "whereis #{@param}", on: @host
18
19
  @parent.expect_none [ 'bin' , @param ]
19
20
  end
20
21
  end
@@ -1,32 +1,33 @@
1
1
 
2
2
  class Service
3
- attr_accessor :param
4
-
5
- def initialize(parent)
6
- @parent = parent
3
+ def initialize(teuton_host, param)
4
+ @teuton_host = teuton_host
5
+ @parent = teuton_host.parent
6
+ @host = teuton_host.host
7
+ @param = param
7
8
  end
8
9
 
9
10
  def is_running?
10
11
  @parent.target("Service #{@param} is running?")
11
- @parent.run "systemctl status #{@param}"
12
+ @parent.run "systemctl status #{@param}", on: @host
12
13
  @parent.expect_one ['Active:', 'running' ]
13
14
  end
14
15
 
15
16
  def is_inactive?
16
17
  @parent.target("Service #{@param} is inactive?")
17
- @parent.run "systemctl status #{@param}"
18
+ @parent.run "systemctl status #{@param}", on: @host
18
19
  @parent.expect_one ['Active:', 'inactive' ]
19
20
  end
20
21
 
21
22
  def is_enable?
22
23
  @parent.target("Service #{@param} is enable?")
23
- @parent.run "systemctl status #{@param}"
24
+ @parent.run "systemctl status #{@param}", on: @host
24
25
  @parent.expect_one ['Loaded:', 'enable' ]
25
26
  end
26
27
 
27
28
  def is_disable?
28
29
  @parent.target("Service #{@param} is disable?")
29
- @parent.run "systemctl status #{@param}"
30
+ @parent.run "systemctl status #{@param}", on: @host
30
31
  @parent.expect_one ['Loaded:', 'disable' ]
31
32
  end
32
33
  end
@@ -0,0 +1,28 @@
1
+
2
+ class TeutonFile
3
+ def initialize(teuton_host, param)
4
+ @teuton_host = teuton_host
5
+ @parent = teuton_host.parent
6
+ @result = @parent.result
7
+ @host = teuton_host.host
8
+ @param = param
9
+ end
10
+
11
+ def exist?
12
+ @parent.target("File #{@param} exists?")
13
+ @parent.run "file #{@param}", on: @host
14
+ @parent.expect @result.grep_v('cannot open').grep(@param).count.eq 1
15
+ end
16
+
17
+ def directory?
18
+ @parent.target("File #{@param} is directory?")
19
+ @parent.run "file #{@param}", on: @host
20
+ @parent.expect @result.grep_v('cannot open').grep(@param).grep('directory').count.eq 1
21
+ end
22
+
23
+ def regular?
24
+ @parent.target("File #{@param} is regular?")
25
+ @parent.run "file #{@param}", on: @host
26
+ @parent.expect @result.grep(@param).grep('directory').count.eq 0
27
+ end
28
+ end
@@ -0,0 +1,31 @@
1
+
2
+ require_relative 'teuton_file'
3
+ require_relative 'package'
4
+ require_relative 'service'
5
+ require_relative 'user'
6
+
7
+ class TeutonHost
8
+ attr_reader :parent
9
+ attr_reader :host
10
+
11
+ def initialize(parent, host = 'localhost')
12
+ @parent = parent
13
+ @host = host
14
+ end
15
+
16
+ def file(param)
17
+ TeutonFile.new(self, param)
18
+ end
19
+
20
+ def package(param)
21
+ Package.new(self, param)
22
+ end
23
+
24
+ def service(param)
25
+ Service.new(self, param)
26
+ end
27
+
28
+ def user(param)
29
+ User.new(self, param)
30
+ end
31
+ end
@@ -1,20 +1,21 @@
1
1
 
2
2
  class User
3
- attr_accessor :param
4
-
5
- def initialize(parent)
6
- @parent = parent
3
+ def initialize(teuton_host, param)
4
+ @teuton_host = teuton_host
5
+ @parent = teuton_host.parent
6
+ @host = teuton_host.host
7
+ @param = param
7
8
  end
8
9
 
9
10
  def exists?
10
11
  @parent.target("User #{@param} exists?")
11
- @parent.run "id #{@param}"
12
- @parent.expect_one @param
12
+ @parent.run "id #{@param}", on: @host
13
+ @parent.expect_one [ 'uid=', @param ]
13
14
  end
14
15
 
15
16
  def is_member_of?(groupname)
16
17
  @parent.target("User #{@param} is member of #{groupname}?")
17
- @parent.run "id #{@param}"
18
+ @parent.run "id #{@param}", on: @host
18
19
  @parent.expect_one [@param, groupname]
19
20
  end
20
21
  end
@@ -115,7 +115,7 @@ class Case
115
115
  alias skip? skip
116
116
 
117
117
  ##
118
- # Show case
118
+ # Show case report data on screen
119
119
  def show
120
120
  @report.show
121
121
  end
@@ -22,8 +22,8 @@ module DSL
22
22
  def goto(host = :localhost, args = {})
23
23
  @result.reset
24
24
  args[:on] = host unless args[:on]
25
- @action[:command] = args[:execute] if args[:execute]
26
- @action[:command] = args[:exec] if args[:exec]
25
+ @action[:command] = args[:execute].to_s if args[:execute]
26
+ @action[:command] = args[:exec].to_s if args[:exec]
27
27
  tempfile(args[:tempfile]) if args[:tempfile]
28
28
  @action[:encoding] = args[:encoding] || 'UTF-8'
29
29
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  ##
4
- # Case class -> DSL module : log function
4
+ # Define DSL#log function
5
5
  module DSL
6
6
  ##
7
7
  # Record log message
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  require_relative '../../../application'
3
+ require 'os'
3
4
 
4
5
  # DSL module methods: assert, missing_method
5
6
  module DSL
@@ -31,7 +32,9 @@ module DSL
31
32
  # * Invoke macro (assert)
32
33
  def method_missing(method, args = {})
33
34
  a = method.to_s
34
- return instance_eval("get(:#{a[0, a.size - 1]})") if a[a.size - 1] == '?'
35
+ if a.start_with?('_') && a.end_with?('_')
36
+ return instance_eval("get(:#{a[1, a.size - 2]})")
37
+ end
35
38
  return macro a[6, a.size], args if a[0,6]=='macro_'
36
39
  macro a, args
37
40
  end
@@ -18,6 +18,7 @@ module DSL
18
18
  ip = get((host + '_ip').to_sym)
19
19
  username = get((host + '_username').to_sym).to_s
20
20
  password = get((host + '_password').to_sym).to_s
21
+ port = get((host + '_port').to_sym) || 22
21
22
 
22
23
  filename = @report.filename + '.' + @report.format.to_s
23
24
  localfilepath = File.join(@report.output_dir, filename)
@@ -32,7 +33,7 @@ module DSL
32
33
 
33
34
  # Upload a file or directory to the remote host
34
35
  begin
35
- Net::SFTP.start(ip, username, password: password) do |sftp|
36
+ Net::SFTP.start(ip, username, password: password, port: port) do |sftp|
36
37
  sftp.upload!(localfilepath, remotefilepath)
37
38
  end
38
39
  verboseln("=> [ OK ] #{(get(:tt_members)[0,15]).ljust(16)} : #{remotefilepath}")
@@ -58,6 +58,7 @@ class Case
58
58
 
59
59
  ##
60
60
  # Fill case report with time information
61
+ # rubocop:disable Metrics/AbcSize
61
62
  def fill_report(start_time, finish_time)
62
63
  @report.head.merge! @config.global
63
64
  @report.head.merge! @config.local
@@ -67,4 +68,5 @@ class Case
67
68
  @report.tail[:finish_time] = finish_time
68
69
  @report.tail[:duration] = finish_time - start_time
69
70
  end
71
+ # rubocop:enable Metrics/AbcSize
70
72
  end
@@ -1,7 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # This is an extension of Result class
4
+ # rubocop:disable Metrics/ClassLength
4
5
  class Result
6
+ # rubocop:disable Metrics/MethodLength
7
+ # Return true when content is equal than input
8
+ # @param input (Object)
5
9
  def eq(input)
6
10
  @expected = input
7
11
 
@@ -21,11 +25,13 @@ class Result
21
25
  end
22
26
  value == input
23
27
  end
28
+ # rubocop:enable Metrics/MethodLength
24
29
  alias eq? eq
25
30
  alias equal eq
26
31
  alias equal? eq
27
32
  alias is_equal? eq
28
33
 
34
+ # rubocop:disable Metrics/MethodLength
29
35
  def neq(external)
30
36
  @expected = "Not equal to #{external}"
31
37
 
@@ -43,10 +49,12 @@ class Result
43
49
  end
44
50
  internal != external
45
51
  end
52
+ # rubocop:enable Metrics/MethodLength
46
53
  alias neq? neq
47
54
  alias not_equal neq
48
55
  alias not_equal? neq
49
56
 
57
+ # rubocop:disable Metrics/MethodLength
50
58
  def ge(input)
51
59
  @expected = "Greater or equal to #{input}"
52
60
  return false if @content.nil? || @content[0].nil?
@@ -64,9 +72,11 @@ class Result
64
72
  end
65
73
  value >= input
66
74
  end
75
+ # rubocop:enable Metrics/MethodLength
67
76
  alias greater_or_equal ge
68
77
  alias greater_or_equal? ge
69
78
 
79
+ # rubocop:disable Metrics/MethodLength
70
80
  def gt(input)
71
81
  @expected = "Greater than #{input}"
72
82
  return false if @content.nil? || @content[0].nil?
@@ -84,9 +94,11 @@ class Result
84
94
  end
85
95
  value > input
86
96
  end
97
+ # rubocop:enable Metrics/MethodLength
87
98
  alias greater gt
88
99
  alias greater_than gt
89
100
 
101
+ # rubocop:disable Metrics/MethodLength
90
102
  def le(input)
91
103
  @expected = "Lesser or equal to #{input}"
92
104
 
@@ -105,9 +117,11 @@ class Result
105
117
  end
106
118
  value <= input
107
119
  end
120
+ # rubocop:enable Metrics/MethodLength
108
121
  alias lesser_or_equal le
109
122
  alias lesser_or_equal? le
110
123
 
124
+ # rubocop:disable Metrics/MethodLength
111
125
  def lt(input)
112
126
  @expected = "Lesser than #{input}"
113
127
  return false if @content.nil? || @content[0].nil?
@@ -125,6 +139,7 @@ class Result
125
139
  end
126
140
  value < input
127
141
  end
142
+ # rubocop:enable Metrics/MethodLength
128
143
  alias lesser lt
129
144
  alias smaller lt
130
145
  alias lesser_than lt
@@ -145,3 +160,4 @@ class Result
145
160
  alias near? near_to?
146
161
  alias near near_to?
147
162
  end
163
+ # rubocop:enable Metrics/ClassLength
@@ -44,7 +44,7 @@ class Result
44
44
  print " [DEBUG] count=#{@content.count} "
45
45
  puts '*' * 20
46
46
  @content.each_with_index do |item, index|
47
- puts format('%2d: %s', index, item)
47
+ puts format('%<index>2d: %<item>s', { index: index, item: item })
48
48
  end
49
49
  puts '*' * 57
50
50
  end
@@ -8,6 +8,7 @@ require_relative 'dsl/log'
8
8
  # * run_local_cmd
9
9
  # * run_remote_cmd
10
10
  # * run_remote_cmd_ssh
11
+ # * reconfigure_command_with_gateway
11
12
  # * run_remote_cmd_telnet
12
13
  class Case
13
14
 
@@ -65,21 +66,45 @@ class Case
65
66
  def run_cmd_remote_ssh(input_hostname)
66
67
  @action[:conn_type] = :ssh
67
68
  hostname = input_hostname.to_s
68
- ip = @config.get((hostname + '_ip').to_sym)
69
- username = @config.get((hostname + '_username').to_sym).to_s
70
- password = @config.get((hostname + '_password').to_sym).to_s
69
+ ip = @config.get("#{hostname}_ip".to_sym).to_s
70
+ username = @config.get("#{hostname}_username".to_sym).to_s
71
+ password = @config.get("#{hostname}_password".to_sym).to_s
72
+ port = @config.get("#{hostname}_port".to_sym).to_i || 22
73
+
74
+ unless @config.get("#{hostname}_route".to_sym) == 'NODATA'
75
+ # Reconfigure command with gateway. Example host1_route: IP.
76
+ hostname2 = hostname
77
+ ip2 = ip
78
+ username2 = username
79
+ password2 = password
80
+ command2 = @action[:command]
81
+ hostname = @config.get("#{hostname}_route".to_sym)
82
+ ip = @config.get("#{hostname}_ip".to_sym).to_s
83
+ username = @config.get("#{hostname}_username".to_sym).to_s
84
+ password = @config.get("#{hostname}_password".to_sym).to_s
85
+ ostype = @config.get("#{hostname}_ostype".to_sym).to_s
86
+
87
+ if ostype.downcase.start_with? 'win'
88
+ # echo y | plink idp@2.tcp.eu.ngrok.io -ssh -P 16256 -pw idp "echo > Desktop\hola.txt"
89
+ @action[:command] = "echo y | plink #{username2}@#{ip2} -ssh -pw #{password2} \"#{command2}\""
90
+ else
91
+ @action[:command] = "sshpass -p #{password2} #{username2}@#{ip2} #{command2}"
92
+ end
93
+ end
94
+
71
95
  text = ''
72
96
  begin
73
97
  if @sessions[hostname].nil?
74
98
  @sessions[hostname] = Net::SSH.start(ip,
75
99
  username,
100
+ port: port,
76
101
  password: password,
77
102
  keepalive: true,
78
103
  timeout: 30,
79
104
  non_interactive: true)
80
105
  end
81
106
  if @sessions[hostname].class == Net::SSH::Connection::Session
82
- text = @sessions[hostname].exec!(@action[:command].to_s)
107
+ text = @sessions[hostname].exec!(@action[:command])
83
108
  end
84
109
  rescue Errno::EHOSTUNREACH
85
110
  @sessions[hostname] = :nosession
@@ -109,6 +134,7 @@ class Case
109
134
  " exec: #{@action[:command]}", :error)
110
135
  end
111
136
  output = encode_and_split(@action[:encoding], text)
137
+ # revise: @result.exitstatus = text.exitstatus
112
138
  @result.content = output
113
139
  @result.content.compact!
114
140
  end
@@ -3,7 +3,7 @@
3
3
  require 'singleton'
4
4
  require_relative '../application'
5
5
  require_relative '../report/report'
6
- require_relative '../project/configfile_reader'
6
+ require_relative '../utils/configfile_reader'
7
7
  require_relative 'case/case'
8
8
  require_relative 'export_manager'
9
9
  require_relative 'main'
@@ -1,6 +1,8 @@
1
1
  require_relative '../application'
2
2
  require_relative 'case_manager'
3
3
 
4
+ # Define filename to be used into our test
5
+ # @param filename (String) Filename to be required
4
6
  def use(filename)
5
7
  filename += '.rb'
6
8
  app = Application.instance
@@ -12,17 +14,25 @@ def use(filename)
12
14
  app.uses << File.basename(findfiles.first)
13
15
  end
14
16
 
17
+ # Define macro. That's a name to predefined target-run-expect evaluation.
18
+ # @param name (String) macro name
19
+ # @param block (Block) macro code
15
20
  def define_macro(name, *args, &block)
16
21
  Application.instance.macros[name] = { args: args, block: block }
17
22
  end
18
23
  alias def_macro define_macro
19
24
  alias defmacro define_macro
20
25
 
26
+ # Define a group of tests
27
+ # @param name (String) Group name
28
+ # @param block (Block) Tests code
21
29
  def group(name, &block)
22
30
  Application.instance.groups << { name: name, block: block }
23
31
  end
24
32
  alias task group
25
33
 
34
+ # Start test
35
+ # @param block (Block) Extra code executed at the end.
26
36
  def play(&block)
27
37
  CaseManager.instance.play(&block)
28
38
  end