metasploit-yard 1.0.0

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.
@@ -0,0 +1,87 @@
1
+ #
2
+ # Gems
3
+ #
4
+
5
+ require 'active_support/core_ext/hash/keys'
6
+
7
+ #
8
+ # Project
9
+ #
10
+
11
+ require 'metasploit/yard/aruba/rvm_env/variable'
12
+
13
+ # Recognizes `export`s of a variable
14
+ class Metasploit::Yard::Aruba::RvmEnv::Export < Metasploit::Yard::Aruba::RvmEnv::Variable
15
+ #
16
+ # CONSTANTS
17
+ #
18
+
19
+ # Matches line with format `export <name>=<quote><value><quote>`
20
+ REGEXP = /\Aexport (?<name>.*?)=(?<quote>"|')(?<value>.*?)\k<quote>\Z/
21
+
22
+ #
23
+ # Attributes
24
+ #
25
+
26
+ # @!attribute value
27
+ # The value to which {Metasploit::Yard::Aruba::RvmEnv::Variable#name} should be set
28
+ #
29
+ # @return [String]
30
+ attr_accessor :value
31
+
32
+ #
33
+ # Class Methods
34
+ #
35
+
36
+ # Parses line of `rvm env` output into an {Export} if it matches {REGEXP}.
37
+ #
38
+ # @param line [String] a line of `rvm env` output
39
+ # @return [Export] if line contains `export`.
40
+ # @return [nil] otherwise
41
+ def self.parse(line)
42
+ # use self:: so subclasses can override
43
+ match = self::REGEXP.match(line)
44
+
45
+ if match
46
+ new(
47
+ name: match[:name],
48
+ value: match[:value]
49
+ )
50
+ end
51
+ end
52
+
53
+ #
54
+ # Instance Methods
55
+ #
56
+
57
+ # @param attributes [Hash{Symbol=>String}]
58
+ # @option attributes [String] :name (see Metasploit::Yard::Aruba::RvmEnv::Variable#name})
59
+ # @option attributes [String] :value (see #value)
60
+ def initialize(attributes={})
61
+ attributes.assert_valid_keys(:name, :value)
62
+
63
+ super(name: attributes[:name])
64
+ @value = attributes[:value]
65
+ end
66
+
67
+ # Whether this export is the same class and has the same {#value} as `other`.
68
+ #
69
+ # @return [true] if `other.class` is `Metasploit::Yard::Aruba::RvmEnv::Export` and `other.value` is {#value}.
70
+ # @return [false] otherwise
71
+ def ==(other)
72
+ super(other) && other.value == self.value
73
+ end
74
+
75
+ # Set {Metasploit::Yard::Aruba::RvmEnv::Variable#name} to {#value}.
76
+ #
77
+ # @param options [Hash{Symbol => Object}]
78
+ # @option options [Metasploit::Yard::Aruba::RvmEnv::Unset] :from the old state of this variable
79
+ # @option options [Object] :world the cucumber world instance for the current scenario
80
+ def change(options={})
81
+ options.assert_valid_keys(:from, :world)
82
+
83
+ world = options.fetch(:world)
84
+
85
+ world.set_env(name, value)
86
+ end
87
+ end
@@ -0,0 +1,47 @@
1
+ #
2
+ # Gems
3
+ #
4
+
5
+ require 'active_support/core_ext/hash/keys'
6
+
7
+ #
8
+ # Project
9
+ #
10
+
11
+ require 'metasploit/yard/aruba/rvm_env'
12
+
13
+ # Recognizes `export`s that are actually prepending values to the pre-existing value as is the case with `PATH`.
14
+ class Metasploit::Yard::Aruba::RvmEnv::Prepend < Metasploit::Yard::Aruba::RvmEnv::Export
15
+ #
16
+ # CONSTANTS
17
+ #
18
+
19
+ # Matches line with format `export <name>=<quote><value>$<name><quote>`. `<value>` will contain trailing
20
+ # `File::PATH_SEPARATOR`, so it can be directly prepended to the current value of `<name>` to get the value to set
21
+ # the environment variable.
22
+ REGEXP = /\Aexport (?<name>.*?)=(?<quote>"|')(?<value>.*?#{File::PATH_SEPARATOR})\$\k<name>\k<quote>\Z/
23
+
24
+ # Replaces {Metasploit::Yard::Aruba::RvmEnv::Export#value `:from` value} with
25
+ # {Metasploit::Yard::Aruba::RvmEnv::Export#value this variable's value}.
26
+ #
27
+ # @param options [Hash{Symbol => Object}]
28
+ # @option options [Metasploit::Yard::Aruba::RvmEnv::Unset] :from the old state of this variable.
29
+ # @option options [Object] :world the cucumber world instance for the current scenario
30
+ def change(options={})
31
+ options.assert_valid_keys(:from, :world)
32
+
33
+ from = options.fetch(:from)
34
+ world = options.fetch(:world)
35
+
36
+ from_directories = from.value.split(File::PATH_SEPARATOR)
37
+ to_directories = value.split(File::PATH_SEPARATOR)
38
+
39
+ path = ENV[name]
40
+
41
+ to_directories.zip(from_directories) do |to_directory, from_directory|
42
+ path = path.gsub(from_directory, to_directory)
43
+ end
44
+
45
+ world.set_env(name, path)
46
+ end
47
+ end
@@ -0,0 +1,56 @@
1
+ #
2
+ # Gems
3
+ #
4
+
5
+ require 'active_support/core_ext/hash/keys'
6
+
7
+ #
8
+ # Project
9
+ #
10
+
11
+ require 'metasploit/yard/aruba/rvm_env/variable'
12
+
13
+ # Recognizes `unset`s of environment variables.
14
+ class Metasploit::Yard::Aruba::RvmEnv::Unset < Metasploit::Yard::Aruba::RvmEnv::Variable
15
+ #
16
+ # CONSTANTS
17
+ #
18
+
19
+ # Matches line with format `unset <name>`
20
+ REGEXP = /\Aunset (?<name>.*?)\Z/
21
+
22
+ #
23
+ # Class Methods
24
+ #
25
+
26
+ # Parses lines of `rvm env` output into a {Prepend} if it matches {REGEXP}
27
+ #
28
+ # @param line [String] a line of `rvm env` output.
29
+ # @return [Unset] if line contains `unset`.
30
+ # @return [nil] otherwise
31
+ def self.parse(line)
32
+ match = REGEXP.match(line)
33
+
34
+ if match
35
+ new(
36
+ name: match[:name]
37
+ )
38
+ end
39
+ end
40
+
41
+ #
42
+ # Instance Methods
43
+ #
44
+
45
+ # Unsets {Metasploit::Yard::Aruba::RvmEnv::Variable#name}.
46
+ #
47
+ # @param options [Hash{Symbol => Object}]
48
+ # @option options [Metasploit::Yard::Aruba::RvmEnv::Unset] :from the old state of this variable
49
+ # @option options [Object] :world the cucumber world instance for the current scenario
50
+ def change(options={})
51
+ options.assert_valid_keys(:from , :world)
52
+
53
+ world = options.fetch(:world)
54
+ world.unset_env(name)
55
+ end
56
+ end
@@ -0,0 +1,44 @@
1
+ #
2
+ # Gems
3
+ #
4
+
5
+ require 'active_support/core_ext/hash/keys'
6
+
7
+ #
8
+ # Project
9
+ #
10
+
11
+ require 'metasploit/yard/aruba/rvm_env'
12
+
13
+ # An environment variable in `rvm env`.
14
+ class Metasploit::Yard::Aruba::RvmEnv::Variable
15
+ #
16
+ # Attributes
17
+ #
18
+
19
+ # @!attribute name
20
+ # The name of variable being manipulated in `rvm env`
21
+ #
22
+ # @return [String]
23
+ attr_accessor :name
24
+
25
+ #
26
+ # Instance Methods
27
+ #
28
+
29
+ # @param attributes [Hash{Symbol=>String}]
30
+ # @option attributes [String] :name (see #name)
31
+ def initialize(attributes={})
32
+ attributes.assert_valid_keys(:name)
33
+
34
+ @name = attributes[:name]
35
+ end
36
+
37
+ # This variable is the same class and has the same {#name} as `other`.
38
+ #
39
+ # @return [true] if `other.class` is `Metasploit::Yard::Aruba::RvmEnv::Variable` and `other.name` is {#name}.
40
+ # @return [false] otherwise
41
+ def ==(other)
42
+ other.class == self.class && other.name == self.name
43
+ end
44
+ end
@@ -0,0 +1,103 @@
1
+ #
2
+ # Gems
3
+ #
4
+
5
+ require 'active_support/core_ext/hash/keys'
6
+
7
+ #
8
+ # Project
9
+ #
10
+
11
+ require 'metasploit/yard/aruba'
12
+
13
+ # Helpers for parsing `rvm env` output
14
+ module Metasploit::Yard::Aruba::RvmEnv
15
+ require 'metasploit/yard/aruba/rvm_env/export'
16
+ require 'metasploit/yard/aruba/rvm_env/prepend'
17
+ require 'metasploit/yard/aruba/rvm_env/unset'
18
+
19
+ #
20
+ # CONSTANTS
21
+ #
22
+
23
+ # Class for parsing lines for `rvm env` in order of precedence
24
+ LINE_PARSER_PRECEDENCE = [
25
+ # must be before `Metasploit::Yard::Aruba::RvmEnv::Export` because
26
+ # `Metasploit::Yard::Aruba::RvmEnv::Export::REGEXP` matches a superset of
27
+ # `Metasploit::Yard::Aruba::RvmEnv::Prepend::REGEXP`
28
+ Metasploit::Yard::Aruba::RvmEnv::Prepend,
29
+ Metasploit::Yard::Aruba::RvmEnv::Export,
30
+ Metasploit::Yard::Aruba::RvmEnv::Unset
31
+ ]
32
+
33
+ # Changes from one `rvm env [@<gemset>]` to another.
34
+ #
35
+ # @param options [Hash{Symbol => Array<Metasploit::Yard::Aruba::RvmEnv::Variable>}]
36
+ # @option options :from [Array<Metasploit::Yard::Aruba::RvmEnv::Variable>] the current rvm env; usually the output of
37
+ # parsing `rvm env`.
38
+ # @option options :to [Array<Metasploit::Yard::Aruba::RvmEnv::Variable>] the new rvm env; usualy the output of parsing
39
+ # `rvm env @<gemset>`
40
+ # @option options [Object] :world the cucumber World instance for the current scenario.
41
+ def self.change(options={})
42
+ options.assert_valid_keys(:from, :to, :world)
43
+
44
+ from_by_name = parsed_to_hash(options.fetch(:from))
45
+ to_by_name = parsed_to_hash(options.fetch(:to))
46
+ world = options.fetch(:world)
47
+
48
+ to_by_name.each do |name, to_variable|
49
+ from_variable = from_by_name[name]
50
+
51
+ # ignore variables that didn't change
52
+ unless to_variable == from_variable
53
+ to_variable.change(
54
+ from: from_variable,
55
+ world: world
56
+ )
57
+ end
58
+ end
59
+ end
60
+
61
+ # Parses the output of `rvm env`.
62
+ #
63
+ # @return [Array<Metasploit::Yard::Aruba::RvmEnv::Variable, #apply>]
64
+ def self.parse(rvm_env)
65
+ rvm_env.each_line.map { |line|
66
+ parse_line(line)
67
+ }
68
+ end
69
+
70
+ # Parses an individual line of `rvm env`
71
+ #
72
+ # @return [Metasploit::Yard::Aruba::RvmEnv::Variable, #apply]
73
+ # @raise [ArgumentError] if no `Class` in {LINE_PARSER_PRECEDENCE} returns a parsed instance.
74
+ def self.parse_line(line)
75
+ parsed = nil
76
+
77
+ LINE_PARSER_PRECEDENCE.each do |line_parser|
78
+ parsed = line_parser.parse(line)
79
+
80
+ if parsed
81
+ break
82
+ end
83
+ end
84
+
85
+ unless parsed
86
+ raise ArgumentError, "No line parser could parse #{line.inspect}"
87
+ end
88
+
89
+ parsed
90
+ end
91
+
92
+ # Converts output of {parse} into Hash that maps {Metasploit::Yard::Aruba::RvmEnv::Variable#name} to the
93
+ # {Metasploit::Yard::Aruba::RvmEnv::Variable}.
94
+ #
95
+ # @param parsed [Array<Metasploit::Yard::Aruba::RvmEnv::Variable>] output of {parse}.
96
+ # @return [Hash{String => Metasploit::Yard::Aruba::RvmEnv::Variable}] Map of
97
+ # {Metasploit::Yard::Aruba::RvmEnv::Variable#name} to the {Metasploit::Yard::Aruba::RvmEnv::Variable}.
98
+ def self.parsed_to_hash(parsed)
99
+ parsed.each_with_object({}) { |variable, variable_by_name|
100
+ variable_by_name[variable.name] = variable
101
+ }
102
+ end
103
+ end
@@ -0,0 +1,6 @@
1
+ require 'metasploit/yard'
2
+
3
+ # Helpers for aruba step definitions for testing `rake yard`
4
+ module Metasploit::Yard::Aruba
5
+
6
+ end
@@ -0,0 +1,12 @@
1
+ require 'rails/railtie'
2
+
3
+ module Metasploit
4
+ module Yard
5
+ # Automatically loads `yard.rake` for any Rails project.
6
+ class Railtie < Rails::Railtie
7
+ rake_tasks do
8
+ load 'tasks/yard.rake'
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,43 @@
1
+ module Metasploit
2
+ module Yard
3
+ # Holds components of {VERSION} as defined by {http://semver.org/spec/v2.0.0.html semantic versioning v2.0.0}.
4
+ module Version
5
+ # The major version number.
6
+ MAJOR = 1
7
+ # The minor version number, scoped to the {MAJOR} version number.
8
+ MINOR = 0
9
+ # The patch number, scoped to the {MINOR} version number.
10
+ PATCH = 0
11
+
12
+ # The full version string, including the {MAJOR}, {MINOR}, {PATCH}, and optionally, the {PRERELEASE} in the
13
+ # {http://semver.org/spec/v2.0.0.html semantic versioning v2.0.0} format.
14
+ #
15
+ # @return [String] '{MAJOR}.{MINOR}.{PATCH}' on master. '{MAJOR}.{MINOR}.{PATCH}-{PRERELEASE}' on any branch
16
+ # other than master.
17
+ def self.full
18
+ version = "#{MAJOR}.#{MINOR}.#{PATCH}"
19
+
20
+ if defined? PRERELEASE
21
+ version = "#{version}-#{PRERELEASE}"
22
+ end
23
+
24
+ version
25
+ end
26
+
27
+ # The full gem version string, including the {MAJOR}, {MINOR}, {PATCH}, and optionally, the {PRERELEASE} in the
28
+ # {http://guides.rubygems.org/specification-reference/#version RubyGems versioning} format.
29
+ #
30
+ # @return [String] '{MAJOR}.{MINOR}.{PATCH}' on master. '{MAJOR}.{MINOR}.{PATCH}.{PRERELEASE}' on any branch
31
+ # other than master.
32
+ def self.gem
33
+ full.gsub('-', '.pre.')
34
+ end
35
+ end
36
+
37
+ # @see Version.gem
38
+ GEM_VERSION = Version.gem
39
+
40
+ # @see Version.full
41
+ VERSION = Version.full
42
+ end
43
+ end
@@ -0,0 +1,18 @@
1
+
2
+ #
3
+ # Project
4
+ #
5
+
6
+ require 'metasploit/yard/version'
7
+
8
+ # The namespace shared between all gems related to
9
+ # [Metasploit Framework](https://github.com/rapid7/metasploit-framework) and
10
+ # [Metasploit Commercial Editions](https://metasploit.com)
11
+ module Metasploit
12
+ # Namespace for this gem.
13
+ module Yard
14
+ if defined?(Rails)
15
+ require 'metasploit/yard/railtie'
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,58 @@
1
+ # @note All options not specific to any given rake task should go in the .yardopts file so they are available to both
2
+ # the below rake tasks and when invoking `yard` from the command line
3
+
4
+ #
5
+ # Gems
6
+ #
7
+ # gems must load explicitly any gem declared in gemspec
8
+ # @see https://github.com/bundler/bundler/issues/2018#issuecomment-6819359
9
+ #
10
+ #
11
+
12
+ require 'yard'
13
+
14
+ namespace :yard do
15
+ YARD::Rake::YardocTask.new(:doc) do |t|
16
+ # --no-stats here as 'stats' task called after will print fuller stats
17
+ t.options = ['--no-stats']
18
+
19
+ t.after = Proc.new {
20
+ Rake::Task['yard:stats'].execute
21
+ }
22
+ end
23
+
24
+ desc "Shows stats for YARD Documentation including listing undocumented modules, classes, constants, and methods"
25
+ task :stats => :environment do
26
+ stats = YARD::CLI::Stats.new
27
+ stats.run('--compact', '--list-undoc')
28
+
29
+ threshold = 100.0
30
+ threshold_path = 'config/yard-stats-threshold'
31
+
32
+ if File.exist?(threshold_path)
33
+ threshold = File.read(threshold_path).to_f
34
+ end
35
+
36
+ # duplicates end of YARD::CLI::Stats#print_statistics
37
+ # @see https://github.com/lsegal/yard/blob/76c7525f46df38f7b24d4b3cb9daeef512fe58e8/lib/yard/cli/stats.rb#L63-L69
38
+ total = stats.instance_eval {
39
+ if @undocumented == 0
40
+ 100
41
+ elsif @total == 0
42
+ 0
43
+ else
44
+ (@total - @undocumented).to_f / @total.to_f * 100
45
+ end
46
+ }
47
+
48
+ if total < threshold
49
+ $stderr.puts "Documentation percentage (%<total>.2f%%) below threshold (%<threshold>.2f%%)" % { total: total, threshold: threshold}
50
+ exit 1
51
+ end
52
+ end
53
+ end
54
+
55
+ # @todo Figure out how to just clone description from yard:doc
56
+ desc "Generate YARD documentation"
57
+ # allow calling namespace to as a task that goes to default task for namespace
58
+ task :yard => ['yard:doc']
@@ -0,0 +1,36 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'metasploit/yard/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "metasploit-yard"
8
+ spec.version = Metasploit::Yard::VERSION
9
+ spec.authors = ["Luke Imhoff"]
10
+ spec.email = ["luke_imhoff@rapid7.com"]
11
+ spec.summary = "yard rake tasks"
12
+ spec.description = "YARD rake tasks used through the metasploit-* gem namespace"
13
+ spec.homepage = "https://github.com/rapid7/"
14
+ spec.license = "BSD-3-Clause"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ # assert_valid_keys
22
+ spec.add_development_dependency 'activesupport'
23
+ spec.add_development_dependency 'aruba'
24
+ spec.add_development_dependency 'bundler', '~> 1.5'
25
+ spec.add_development_dependency 'codeclimate-test-reporter'
26
+ spec.add_development_dependency 'coveralls'
27
+ spec.add_development_dependency 'cucumber'
28
+ spec.add_development_dependency 'rspec', '~> 3.0'
29
+ spec.add_development_dependency 'simplecov'
30
+
31
+ spec.add_runtime_dependency 'rake'
32
+ spec.add_runtime_dependency 'yard'
33
+
34
+ # Ruby 1.9 JSON Hash syntax is used
35
+ spec.required_ruby_version = '>= 1.9'
36
+ end
@@ -0,0 +1,143 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Metasploit::Yard::Version do
4
+ context 'CONSTANTS' do
5
+ context 'MAJOR' do
6
+ subject(:major) do
7
+ described_class::MAJOR
8
+ end
9
+
10
+ it { is_expected.to be_a Integer }
11
+ end
12
+
13
+ context 'MINOR' do
14
+ subject(:minor) do
15
+ described_class::MINOR
16
+ end
17
+
18
+ it { is_expected.to be_a Integer }
19
+ end
20
+
21
+ context 'PATCH' do
22
+ subject(:patch) do
23
+ described_class::PATCH
24
+ end
25
+
26
+ it { is_expected.to be_a Integer }
27
+ end
28
+
29
+ pull_request = ENV['TRAVIS_PULL_REQUEST']
30
+
31
+ # a pull request cannot check PRERELEASE because it will be tested in the target branch, but the source itself
32
+ # is from the source branch and so has the source branch PRERELEASE.
33
+ #
34
+ # PRERELEASE can only be set appropriately for a merge by merging to the target branch and then updating PRERELEASE
35
+ # on the target branch before committing and/or pushing to github and travis-ci.
36
+ if pull_request.nil? || pull_request == 'false'
37
+ context 'PREPRELEASE' do
38
+ subject(:prerelease) do
39
+ described_class::PRERELEASE
40
+ end
41
+
42
+ branch = ENV['TRAVIS_BRANCH']
43
+
44
+ if branch.nil? || branch.empty?
45
+ branch = `git rev-parse --abbrev-ref HEAD`.strip
46
+ end
47
+
48
+ if branch == 'master'
49
+ it 'does not have a PRERELEASE' do
50
+ expect(defined? described_class::PRERELEASE).to be_nil
51
+ end
52
+ else
53
+ branch_regex = %r{\A(?:refs/remotes/)?(?<type>bug|chore|feature|staging)(/(?<story>[^/]+))?/(?<prerelease>[^\/]+)\z}
54
+ match = branch.match(branch_regex)
55
+
56
+ if match
57
+ it 'matches the branch relative name' do
58
+ expected_prerelease = match[:prerelease]
59
+
60
+ expect(defined? described_class::PRERELEASE).not_to be_nil,
61
+ "PRERELEASE should be defined as #{expected_prerelease.inspect}"
62
+ expect(prerelease).to eq(expected_prerelease)
63
+ end
64
+ else
65
+ tag_regex = /\Av(?<major>\d+).(?<minor>\d+).(?<patch>\d+)(\.pre\.(?<prerelease>.*))?\z/
66
+ # travis-ci sets TRAVIS_BRANCH to the tag name for tag builds
67
+ match = branch.match(tag_regex)
68
+
69
+ if match
70
+ tag_prerelease = match[:prerelease]
71
+
72
+ if tag_prerelease
73
+ it 'matches the tag prerelease converted from a gem version to a VERSION' do
74
+ expect(prerelease).to eq(tag_prerelease.gsub('.pre.', '-'))
75
+ end
76
+ else
77
+ it 'does not have a PRERELEASE' do
78
+ expect(defined? described_class::PRERELEASE).to be_nil
79
+ end
80
+ end
81
+ else
82
+ it 'has a abbreviated reference that can be parsed for prerelease' do
83
+ fail "Do not know how to parse #{branch.inspect} for PRERELEASE"
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+
92
+ context 'full' do
93
+ subject(:full) do
94
+ described_class.full
95
+ end
96
+
97
+ #
98
+ # lets
99
+ #
100
+
101
+ let(:major) do
102
+ 1
103
+ end
104
+
105
+ let(:minor) do
106
+ 2
107
+ end
108
+
109
+ let(:patch) do
110
+ 3
111
+ end
112
+
113
+ before(:each) do
114
+ stub_const("#{described_class}::MAJOR", major)
115
+ stub_const("#{described_class}::MINOR", minor)
116
+ stub_const("#{described_class}::PATCH", patch)
117
+ end
118
+
119
+ context 'with PRERELEASE' do
120
+ let(:prerelease) do
121
+ 'prerelease'
122
+ end
123
+
124
+ before(:each) do
125
+ stub_const("#{described_class}::PRERELEASE", prerelease)
126
+ end
127
+
128
+ it 'is <major>.<minor>.<patch>-<prerelease>' do
129
+ expect(full).to eq("#{major}.#{minor}.#{patch}-#{prerelease}")
130
+ end
131
+ end
132
+
133
+ context 'without PRERELEASE' do
134
+ before(:each) do
135
+ hide_const("#{described_class}::PRERELEASE")
136
+ end
137
+
138
+ it 'is <major>.<minor>.<patch>' do
139
+ expect(full).to eq("#{major}.#{minor}.#{patch}")
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Metasploit::Yard do
4
+ context 'CONSTANTS' do
5
+ context 'VERSION' do
6
+ subject(:version) {
7
+ described_class::VERSION
8
+ }
9
+
10
+ it 'is Metasploit::Yard::Version.full' do
11
+ expect(version).to eq(Metasploit::Yard::Version.full)
12
+ end
13
+ end
14
+ end
15
+ end