aruba 0.7.4 → 0.8.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (141) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.nav +12 -0
  4. data/.rspec +1 -0
  5. data/.rubocop.yml +12 -0
  6. data/.simplecov +2 -0
  7. data/.travis.yml +5 -6
  8. data/Gemfile +53 -26
  9. data/History.md +17 -0
  10. data/LICENSE +1 -1
  11. data/README.md +45 -19
  12. data/Rakefile +12 -2
  13. data/TODO.md +3 -0
  14. data/aruba.gemspec +19 -8
  15. data/cucumber.yml +1 -1
  16. data/features/api/cd.feature +119 -0
  17. data/features/api/command/run.feature +37 -0
  18. data/features/api/command/which.feature +37 -0
  19. data/features/api/environment/append_environment_variable.feature +118 -0
  20. data/features/api/environment/prepend_environment_variable.feature +118 -0
  21. data/features/api/environment/set_environment_variable.feature +252 -0
  22. data/features/configuration/exit_timeout.feature +51 -0
  23. data/features/configuration/fixtures_directories.feature +31 -0
  24. data/features/configuration/fixtures_path_prefix.feature +24 -0
  25. data/features/configuration/io_timeout.feature +31 -0
  26. data/features/configuration/keep_ansi.feature +31 -0
  27. data/features/configuration/root_directory.feature +31 -0
  28. data/features/configuration/working_directory.feature +32 -0
  29. data/features/fixtures/cli-app/.gitignore +9 -0
  30. data/features/fixtures/cli-app/.rspec +2 -0
  31. data/features/fixtures/cli-app/README.md +34 -0
  32. data/features/fixtures/cli-app/Rakefile +1 -0
  33. data/features/fixtures/cli-app/bin/cli +6 -0
  34. data/features/fixtures/cli-app/cli-app.gemspec +26 -0
  35. data/features/fixtures/cli-app/features/support/env.rb +1 -0
  36. data/features/fixtures/cli-app/lib/cli/app.rb +13 -0
  37. data/features/fixtures/cli-app/lib/cli/app/version.rb +5 -0
  38. data/features/fixtures/cli-app/script/console +14 -0
  39. data/features/fixtures/cli-app/spec/cli/app_spec.rb +7 -0
  40. data/features/fixtures/cli-app/spec/spec_helper.rb +10 -0
  41. data/features/fixtures/copy/file.txt +1 -1
  42. data/features/hooks/after/command.feature +34 -0
  43. data/features/hooks/before/command.feature +61 -0
  44. data/features/matchers/directory/have_sub_directory.feature +110 -0
  45. data/features/matchers/file/be_existing_file.feature +82 -0
  46. data/features/matchers/file/have_file_content.feature +123 -0
  47. data/features/matchers/file/have_file_size.feature +107 -0
  48. data/features/matchers/path/be_an_absolute_path.feature +74 -0
  49. data/features/matchers/path/be_an_existing_path.feature +97 -0
  50. data/features/matchers/path/have_permissions.feature +118 -0
  51. data/features/matchers/timeouts.feature +48 -0
  52. data/features/step_definitions/aruba_dev_steps.rb +69 -1
  53. data/features/steps/commands/exit_statuses.feature +136 -0
  54. data/features/steps/commands/in_process.feature +129 -0
  55. data/features/steps/commands/run.feature +36 -0
  56. data/features/steps/environment/home_variable.feature +49 -0
  57. data/features/steps/environment/set_environment_variable.feature +34 -0
  58. data/features/support/aruba.rb +5 -0
  59. data/features/support/env.rb +8 -4
  60. data/lib/aruba.rb +20 -8
  61. data/lib/aruba/announcer.rb +1 -0
  62. data/lib/aruba/api.rb +18 -1179
  63. data/lib/aruba/api/command.rb +351 -0
  64. data/lib/aruba/api/core.rb +141 -0
  65. data/lib/aruba/api/deprecated.rb +549 -0
  66. data/lib/aruba/api/environment.rb +61 -0
  67. data/lib/aruba/api/filesystem.rb +305 -0
  68. data/lib/aruba/api/rvm.rb +39 -0
  69. data/lib/aruba/aruba_path.rb +75 -0
  70. data/lib/aruba/basic_configuration.rb +208 -0
  71. data/lib/aruba/basic_configuration/option.rb +25 -0
  72. data/lib/aruba/config.rb +43 -30
  73. data/lib/aruba/config/jruby.rb +14 -0
  74. data/lib/aruba/config_wrapper.rb +17 -0
  75. data/lib/aruba/contracts/relative_path.rb +13 -0
  76. data/lib/aruba/creators/aruba_file_creator.rb +32 -0
  77. data/lib/aruba/creators/aruba_fixed_size_file_creator.rb +32 -0
  78. data/lib/aruba/cucumber.rb +87 -53
  79. data/lib/aruba/cucumber/hooks.rb +65 -10
  80. data/lib/aruba/environment.rb +121 -0
  81. data/lib/aruba/errors.rb +3 -0
  82. data/lib/aruba/extensions/string/strip.rb +24 -0
  83. data/lib/aruba/hooks.rb +54 -0
  84. data/lib/aruba/jruby.rb +4 -9
  85. data/lib/aruba/matchers/command.rb +1 -79
  86. data/lib/aruba/matchers/command/be_successfully_executed.rb +30 -0
  87. data/lib/aruba/matchers/command/have_exit_status.rb +47 -0
  88. data/lib/aruba/matchers/command/have_finished_in_time.rb +42 -0
  89. data/lib/aruba/matchers/directory.rb +1 -59
  90. data/lib/aruba/matchers/directory/be_an_existing_directory.rb +34 -0
  91. data/lib/aruba/matchers/directory/have_sub_directory.rb +49 -0
  92. data/lib/aruba/matchers/file.rb +1 -177
  93. data/lib/aruba/matchers/file/be_an_existing_file.rb +34 -0
  94. data/lib/aruba/matchers/file/have_file_content.rb +58 -0
  95. data/lib/aruba/matchers/file/have_file_size.rb +43 -0
  96. data/lib/aruba/matchers/file/have_same_file_content.rb +44 -0
  97. data/lib/aruba/matchers/path.rb +1 -99
  98. data/lib/aruba/matchers/path/a_path_matching_pattern.rb +21 -0
  99. data/lib/aruba/matchers/path/be_an_absolute_path.rb +32 -0
  100. data/lib/aruba/matchers/path/be_an_existing_path.rb +33 -0
  101. data/lib/aruba/matchers/path/have_permissions.rb +60 -0
  102. data/lib/aruba/matchers/path/match_path_pattern.rb +41 -0
  103. data/lib/aruba/matchers/rspec.rb +0 -0
  104. data/lib/aruba/matchers/rspec_matcher_include_regexp.rb +1 -1
  105. data/lib/aruba/platform.rb +230 -0
  106. data/lib/aruba/process_monitor.rb +23 -5
  107. data/lib/aruba/processes/basic_process.rb +35 -1
  108. data/lib/aruba/processes/debug_process.rb +26 -15
  109. data/lib/aruba/processes/in_process.rb +21 -9
  110. data/lib/aruba/processes/spawn_process.rb +29 -19
  111. data/lib/aruba/reporting.rb +2 -0
  112. data/lib/aruba/rspec.rb +61 -13
  113. data/lib/aruba/runtime.rb +33 -0
  114. data/script/bootstrap +4 -6
  115. data/spec/aruba/api/runtime_spec.rb +28 -0
  116. data/spec/aruba/api_spec.rb +129 -126
  117. data/spec/aruba/aruba_path_spec.rb +65 -0
  118. data/spec/aruba/basic_configuration_spec.rb +5 -0
  119. data/spec/aruba/config_wrapper_spec.rb +25 -0
  120. data/spec/aruba/configuration_spec.rb +5 -0
  121. data/spec/aruba/jruby_spec.rb +34 -18
  122. data/spec/aruba/matchers/directory_spec.rb +6 -7
  123. data/spec/aruba/matchers/file_spec.rb +16 -20
  124. data/spec/aruba/matchers/path_spec.rb +14 -11
  125. data/spec/aruba/rspec_spec.rb +15 -0
  126. data/spec/aruba/runtime_spec.rb +29 -0
  127. data/spec/aruba/spawn_process_spec.rb +2 -2
  128. data/spec/spec_helper.rb +10 -2
  129. data/spec/support/configs/rspec.rb +1 -1
  130. data/spec/support/matchers/option.rb +35 -0
  131. data/spec/support/shared_contexts/aruba.rb +10 -8
  132. data/spec/support/shared_examples/configuration.rb +116 -0
  133. metadata +182 -33
  134. data/.rvmrc +0 -1
  135. data/features/before_cmd_hooks.feature +0 -61
  136. data/features/command_environment_variables.feature +0 -31
  137. data/features/custom_ruby_process.feature +0 -12
  138. data/features/exit_statuses.feature +0 -30
  139. data/features/support/custom_main.rb +0 -28
  140. data/lib/aruba/matchers/mode.rb +0 -52
  141. data/lib/aruba/utils.rb +0 -21
@@ -0,0 +1,58 @@
1
+ # @!method have_file_content(content)
2
+ # This matchers checks if <file> has content. `content` can be a string,
3
+ # regexp or an RSpec matcher.
4
+ #
5
+ # @param [String, Regexp, Matcher] content
6
+ # Specifies the content of the file
7
+ #
8
+ # @return [TrueClass, FalseClass] The result
9
+ #
10
+ # false:
11
+ # * if file does not exist
12
+ # * if file content is not equal string
13
+ # * if file content does not include regexp
14
+ # * if file content does not match the content specification
15
+ #
16
+ # true:
17
+ # * if file content includes regexp
18
+ # * if file content is equal string
19
+ # * if file content matches the content specification
20
+ #
21
+ # @example Use matcher with string
22
+ #
23
+ # RSpec.describe do
24
+ # it { expect(file1).to have_file_content('a') }
25
+ # end
26
+ #
27
+ # @example Use matcher with regexp
28
+ #
29
+ # RSpec.describe do
30
+ # it { expect(file1).to have_file_content(/a/) }
31
+ # end
32
+ #
33
+ # @example Use matcher with an RSpec matcher
34
+ #
35
+ # RSpec.describe do
36
+ # it { expect(file1).to have_file_content(a_string_starting_with 'a') }
37
+ # it { expect(files1).to include a_file_having_content(a_string_starting_with 'a') }
38
+ # end
39
+ RSpec::Matchers.define :have_file_content do |expected|
40
+ match do |actual|
41
+ stop_processes!
42
+
43
+ next false unless file? actual
44
+
45
+ @actual = read(actual).join("\n").chomp
46
+ @expected = if expected.is_a? String
47
+ expected.chomp
48
+ else
49
+ expected
50
+ end
51
+
52
+ values_match?(@expected, @actual)
53
+ end
54
+
55
+ description { "have file content: #{description_of expected}" }
56
+ end
57
+
58
+ RSpec::Matchers.alias_matcher :a_file_having_content, :have_file_content
@@ -0,0 +1,43 @@
1
+ # @!method have_file_size(size)
2
+ # This matchers checks if path has file size
3
+ #
4
+ # @param [Fixnum] size
5
+ # The size to check
6
+ #
7
+ # @return [TrueClass, FalseClass] The result
8
+ #
9
+ # false:
10
+ # * if path does not have size
11
+ # true:
12
+ # * if path has size
13
+ #
14
+ # @example Use matcher
15
+ #
16
+ # RSpec.describe do
17
+ # it { expect('file.txt').to have_file_size(0) }
18
+ # it { expect(%w(file.txt file2.txt)).to all have_file_size(0) }
19
+ # it { expect(%w(file.txt file2.txt)).to include a_file_of_size(0) }
20
+ # end
21
+ RSpec::Matchers.define :have_file_size do |expected|
22
+ match do |actual|
23
+ stop_processes!
24
+
25
+ next false unless file?(actual)
26
+
27
+ @old_actual = actual
28
+ @actual = File.size(expand_path(actual))
29
+ @expected = expected.to_i
30
+
31
+ values_match?(@expected, @actual)
32
+ end
33
+
34
+ failure_message do |actual|
35
+ format("expected that file \"%s\" has size \"%s\", but has \"%s\"", @old_actual, @actual, @expected)
36
+ end
37
+
38
+ failure_message_when_negated do |actual|
39
+ format("expected that file \"%s\" does not have size \"%s\", but has \"%s\"", @old_actual, @actual, @expected)
40
+ end
41
+ end
42
+
43
+ RSpec::Matchers.alias_matcher :a_file_of_size, :have_file_size
@@ -0,0 +1,44 @@
1
+ require 'fileutils'
2
+
3
+ # @!method have_same_file_content_like(file_name)
4
+ # This matchers checks if <file1> has the same content like <file2>
5
+ #
6
+ # @param [String] file_name
7
+ # The name of the file which should be compared with the file in the
8
+ # `expect()`-call.
9
+ #
10
+ # @return [TrueClass, FalseClass] The result
11
+ #
12
+ # false:
13
+ # * if file1 is not equal file2
14
+ # true:
15
+ # * if file1 is equal file2
16
+ #
17
+ # @example Use matcher
18
+ #
19
+ # RSpec.describe do
20
+ # it { expect(file1).to have_same_file_content_like(file2) }
21
+ # it { expect(files).to include a_file_with_same_content_like(file2) }
22
+ # end
23
+ RSpec::Matchers.define :have_same_file_content_like do |expected|
24
+ match do |actual|
25
+ stop_processes!
26
+
27
+ next false unless file?(actual) && file?(expected)
28
+
29
+ @actual = expand_path(actual)
30
+ @expected = expand_path(expected)
31
+
32
+ FileUtils.compare_file(@actual,@expected)
33
+ end
34
+
35
+ failure_message do |actual|
36
+ format("expected that file \"%s\" is the same as file \"%s\".", actual, expected)
37
+ end
38
+
39
+ failure_message_when_negated do |actual|
40
+ format("expected that file \"%s\" differs from file \"%s\".", actual, expected)
41
+ end
42
+ end
43
+
44
+ RSpec::Matchers.alias_matcher :a_file_with_same_content_like, :have_same_file_content_like
@@ -1,99 +1 @@
1
- # @!method match_path_pattern(pattern)
2
- # This matchers checks if <files>/directories match <pattern>
3
- #
4
- # @param [String, Regexp] pattern
5
- # The pattern to use.
6
- #
7
- # @return [TrueClass, FalseClass] The result
8
- #
9
- # false:
10
- # * if there are no files/directories which match the pattern
11
- # true:
12
- # * if there are files/directories which match the pattern
13
- #
14
- # @example Use matcher with regex
15
- #
16
- # RSpec.describe do
17
- # it { expect(Dir.glob(**/*)).to match_file_pattern(/.txt$/) }
18
- # end
19
- #
20
- # @example Use matcher with string
21
- #
22
- # RSpec.describe do
23
- # it { expect(Dir.glob(**/*)).to match_file_pattern('.txt$') }
24
- # end
25
- RSpec::Matchers.define :match_path_pattern do |_|
26
- match do |actual|
27
- next !actual.select { |a| a == expected }.empty? if expected.is_a? String
28
-
29
- !actual.grep(expected).empty?
30
- end
31
-
32
- failure_message do |actual|
33
- format("expected that path \"%s\" matches pattern \"%s\".", actual.join(", "), expected)
34
- end
35
-
36
- failure_message_when_negated do |actual|
37
- format("expected that path \"%s\" does not match pattern \"%s\".", actual.join(", "), expected)
38
- end
39
- end
40
-
41
- # @!method be_existing_path
42
- # This matchers checks if <path> exists in filesystem
43
- #
44
- # @return [TrueClass, FalseClass] The result
45
- #
46
- # false:
47
- # * if path does not exist
48
- # true:
49
- # * if path exists
50
- #
51
- # @example Use matcher
52
- #
53
- # RSpec.describe do
54
- # it { expect(file).to be_existing_path }
55
- # it { expect(directory).to be_existing_path }
56
- # end
57
- RSpec::Matchers.define :be_existing_path do |_|
58
- match do |actual|
59
- exist?(actual)
60
- end
61
-
62
- failure_message do |actual|
63
- format("expected that path \"%s\" exists", actual)
64
- end
65
-
66
- failure_message_when_negated do |actual|
67
- format("expected that path \"%s\" does not exist", actual)
68
- end
69
- end
70
-
71
- # @!method be_absolute_path
72
- # This matchers checks if <path> exists in filesystem
73
- #
74
- # @return [TrueClass, FalseClass] The result
75
- #
76
- # false:
77
- # * if path is not absolute
78
- # true:
79
- # * if path is absolute
80
- #
81
- # @example Use matcher
82
- #
83
- # RSpec.describe do
84
- # it { expect(file).to be_absolute_path }
85
- # it { expect(directory).to be_absolute_path }
86
- # end
87
- RSpec::Matchers.define :be_absolute_path do |_|
88
- match do |actual|
89
- absolute?(actual)
90
- end
91
-
92
- failure_message do |actual|
93
- format("expected that path \"%s\" is absolute, but it's not", actual)
94
- end
95
-
96
- failure_message_when_negated do |actual|
97
- format("expected that path \"%s\" is not absolute, but it is", actual)
98
- end
99
- end
1
+ Aruba::Platform.require_matching_files('../path/**/*.rb', __FILE__)
@@ -0,0 +1,21 @@
1
+ # @!method a_path_matching_pattern(/pattern/)
2
+ # This matchers checks if <path> matches pattern. `pattern` can be a string,
3
+ # regexp or an RSpec matcher.
4
+ #
5
+ # @param [String, Regexp, Matcher] pattern
6
+ # Specifies the pattern
7
+ #
8
+ # @return [TrueClass, FalseClass] The result
9
+ #
10
+ # false:
11
+ # * if pattern does not match
12
+ #
13
+ # true:
14
+ # * if pattern matches
15
+ #
16
+ # @example Use matcher with regexp
17
+ #
18
+ # RSpec.describe do
19
+ # it { expect(files).to include a_path_matching_pattern /asdf/ }
20
+ # end
21
+ RSpec::Matchers.alias_matcher :a_path_matching_pattern, :match
@@ -0,0 +1,32 @@
1
+ # @!method be_an_absolute_path
2
+ # This matchers checks if <path> exists in filesystem
3
+ #
4
+ # @return [TrueClass, FalseClass] The result
5
+ #
6
+ # false:
7
+ # * if path is not absolute
8
+ # true:
9
+ # * if path is absolute
10
+ #
11
+ # @example Use matcher
12
+ #
13
+ # RSpec.describe do
14
+ # it { expect(file).to be_an_absolute_path }
15
+ # it { expect(directory).to be_an_absolute_path }
16
+ # it { expect(directories).to include an_absolute_path }
17
+ # end
18
+ RSpec::Matchers.define :be_an_absolute_path do |_|
19
+ match do |actual|
20
+ absolute?(actual)
21
+ end
22
+
23
+ failure_message do |actual|
24
+ format("expected that path \"%s\" is absolute, but it's not", actual)
25
+ end
26
+
27
+ failure_message_when_negated do |actual|
28
+ format("expected that path \"%s\" is not absolute, but it is", actual)
29
+ end
30
+ end
31
+
32
+ RSpec::Matchers.alias_matcher :an_absolute_path, :be_an_absolute_path
@@ -0,0 +1,33 @@
1
+ # @!method be_an_existing_path
2
+ # This matchers checks if <path> exists in filesystem
3
+ #
4
+ # @return [TrueClass, FalseClass] The result
5
+ #
6
+ # false:
7
+ # * if path does not exist
8
+ # true:
9
+ # * if path exists
10
+ #
11
+ # @example Use matcher
12
+ #
13
+ # RSpec.describe do
14
+ # it { expect(file).to be_an_existing_path }
15
+ # it { expect(directory).to be_an_existing_path }
16
+ # it { expect(all_directories).to all be_an_existing_path }
17
+ # it { expect(all_directories).to include an_existing_path }
18
+ # end
19
+ RSpec::Matchers.define :be_an_existing_path do |_|
20
+ match do |actual|
21
+ exist?(actual)
22
+ end
23
+
24
+ failure_message do |actual|
25
+ format("expected that path \"%s\" exists", actual)
26
+ end
27
+
28
+ failure_message_when_negated do |actual|
29
+ format("expected that path \"%s\" does not exist", actual)
30
+ end
31
+ end
32
+
33
+ RSpec::Matchers.alias_matcher :an_existing_path, :be_an_existing_path
@@ -0,0 +1,60 @@
1
+ # @!method have_permissions(permissions)
2
+ # This matchers checks if <file> or <directory> has <perm> permissions
3
+ #
4
+ # @param [Fixnum, String] permissions
5
+ # The permissions as octal number, e.g. `0700`, or String, e.g. `'0700'`
6
+ #
7
+ # @return [TrueClass, FalseClass] The result
8
+ #
9
+ # false:
10
+ # * if file has permissions
11
+ # true:
12
+ # * if file does not have permissions
13
+ #
14
+ # @example Use matcher with octal number
15
+ #
16
+ # RSpec.describe do
17
+ # it { expect(file).to have_permissions(0700) }
18
+ # it { expect(directory).to have_permissions(0700) }
19
+ # end
20
+ #
21
+ # @example Use matcher with string
22
+ #
23
+ # RSpec.describe do
24
+ # it { expect(file).to have_permissions('0700') }
25
+ # it { expect(files).to include a_path_with_permissions('0700') }
26
+ # it { expect(directory).to have_permissions('0700') }
27
+ # it { expect(directories).to include a_path_with_permissions('0700') }
28
+ # end
29
+ RSpec::Matchers.define :have_permissions do |expected|
30
+ def permissions(file)
31
+ @actual = format("%o", File::Stat.new(file).mode)[-4,4].gsub(/^0*/, '')
32
+ end
33
+
34
+ match do |actual|
35
+ stop_processes!
36
+
37
+ @old_actual = actual
38
+ @actual = permissions(expand_path(@old_actual))
39
+
40
+ @expected = if expected.is_a? Integer
41
+ expected.to_s(8)
42
+ elsif expected.is_a? String
43
+ expected.gsub(/^0*/, '')
44
+ else
45
+ expected
46
+ end
47
+
48
+ values_match? @expected, @actual
49
+ end
50
+
51
+ failure_message do |actual|
52
+ format("expected that path \"%s\" has permissions \"%s\", but has \"%s\".", @old_actual, @expected, @actual)
53
+ end
54
+
55
+ failure_message_when_negated do |actual|
56
+ format("expected that path \"%s\" does not have permissions \"%s\", but has \"%s\".", @old_actual, @expected, @actual)
57
+ end
58
+ end
59
+
60
+ RSpec::Matchers.alias_matcher :a_path_having_permissions, :have_permissions
@@ -0,0 +1,41 @@
1
+ # @!method match_path_pattern(pattern)
2
+ # This matchers checks if <files>/directories match <pattern>
3
+ #
4
+ # @param [String, Regexp] pattern
5
+ # The pattern to use.
6
+ #
7
+ # @return [TrueClass, FalseClass] The result
8
+ #
9
+ # false:
10
+ # * if there are no files/directories which match the pattern
11
+ # true:
12
+ # * if there are files/directories which match the pattern
13
+ #
14
+ # @example Use matcher with regex
15
+ #
16
+ # RSpec.describe do
17
+ # it { expect(Dir.glob(**/*)).to match_file_pattern(/.txt$/) }
18
+ # end
19
+ #
20
+ # @example Use matcher with string
21
+ #
22
+ # RSpec.describe do
23
+ # it { expect(Dir.glob(**/*)).to match_file_pattern('.txt$') }
24
+ # end
25
+ RSpec::Matchers.define :match_path_pattern do |_|
26
+ match do |actual|
27
+ Aruba::Platform.deprecated('The use of `expect().to match_path_pattern` is deprecated. Please use `expect().to include pattern /regex/` instead.')
28
+
29
+ next !actual.select { |a| a == expected }.empty? if expected.is_a? String
30
+
31
+ !actual.grep(expected).empty?
32
+ end
33
+
34
+ failure_message do |actual|
35
+ format("expected that path \"%s\" matches pattern \"%s\".", actual.join(", "), expected)
36
+ end
37
+
38
+ failure_message_when_negated do |actual|
39
+ format("expected that path \"%s\" does not match pattern \"%s\".", actual.join(", "), expected)
40
+ end
41
+ end
File without changes
@@ -18,7 +18,7 @@
18
18
  # end
19
19
  RSpec::Matchers.define :include_regexp do |expected|
20
20
  match do |actual|
21
- warn('The use of "include_regexp"-matchers is deprecated. It will be removed soon.')
21
+ Aruba::Platform.deprecated('The use of "include_regexp"-matchers is deprecated. It will be removed soon.')
22
22
 
23
23
  !actual.grep(expected).empty?
24
24
  end