metasploit-erd 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.
@@ -0,0 +1,130 @@
1
+ require 'spec_helper'
2
+
3
+ describe Metasploit::ERD::Entity::Namespace do
4
+ include_context 'ActiveRecord::Base.descendants cleaner'
5
+
6
+ subject(:namespace_entity) {
7
+ described_class.new(namespace_name)
8
+ }
9
+
10
+ let(:namespace_name) {
11
+ 'Namespace'
12
+ }
13
+
14
+ it_should_behave_like 'Metasploit::ERD::Clusterable' do
15
+ let(:entity) {
16
+ described_class.new('Dummy')
17
+ }
18
+ end
19
+
20
+ context '#classes' do
21
+ subject(:namespace_entities) {
22
+ namespace_entity.classes
23
+ }
24
+
25
+ #
26
+ # lets
27
+ #
28
+
29
+ let(:other_namespace_name) {
30
+ 'OtherNamespace'
31
+ }
32
+
33
+ #
34
+ # Callbacks
35
+ #
36
+
37
+ before(:each) do
38
+ stub_const(other_namespace_name, Module.new)
39
+ stub_const(namespace_name, Module.new)
40
+ end
41
+
42
+ context 'with ActiveRecord::Base descendants' do
43
+ let(:child_name) {
44
+ 'Child'
45
+ }
46
+
47
+ let(:childnamespace_name) {
48
+ 'ChildNamespace'
49
+ }
50
+
51
+ let(:grandchild_name) do
52
+ 'GrandChild'
53
+ end
54
+
55
+ let(:other_namespaced_child_name) {
56
+ "#{other_namespace_name}::#{child_name}"
57
+ }
58
+
59
+ let(:other_namespaced_child) {
60
+ other_namespaced_child_name.constantize
61
+ }
62
+
63
+ let(:namespaced_child) do
64
+ namespaced_child_name.constantize
65
+ end
66
+
67
+ let(:namespaced_child_name) {
68
+ "#{namespace_name}::#{child_name}"
69
+ }
70
+
71
+ let(:namespaced_child_namespace_name) {
72
+ "#{namespace_name}::#{childnamespace_name}"
73
+ }
74
+
75
+ let(:namespaced_grandchild) {
76
+ namespaced_grandchild_name.constantize
77
+ }
78
+
79
+ let(:namespaced_grandchild_name) {
80
+ "#{namespaced_child_namespace_name}::#{grandchild_name}"
81
+ }
82
+
83
+ #
84
+ # Callbacks
85
+ #
86
+
87
+ before(:each) do
88
+ stub_const(other_namespaced_child_name, Class.new(ActiveRecord::Base))
89
+
90
+ stub_const(namespaced_child_name, Class.new(ActiveRecord::Base))
91
+
92
+ stub_const(namespaced_child_namespace_name, Module.new)
93
+ stub_const(namespaced_grandchild_name, Class.new(ActiveRecord::Base))
94
+ end
95
+
96
+ it 'does not include entities from other namespaces' do
97
+ expect(namespace_entities).not_to include(other_namespaced_child)
98
+ end
99
+
100
+ it 'includes direct children of the namespace' do
101
+ expect(namespace_entities).to include(namespaced_child)
102
+ end
103
+
104
+ it 'includes indirect descendants of the namespace' do
105
+ expect(namespace_entities).to include(namespaced_grandchild)
106
+ end
107
+ end
108
+
109
+ context 'without ActiveRecord::Base descendants' do
110
+ it { should be_empty }
111
+ end
112
+ end
113
+
114
+ context '#cluster' do
115
+ subject(:cluster) {
116
+ namespace_entity.cluster
117
+ }
118
+
119
+ it 'created a Metasploit::ERD::Cluster containing #classes' do
120
+ classes = Array.new(2) { |n|
121
+ double("Class#{n}")
122
+ }
123
+
124
+ expect(namespace_entity).to receive(:classes).and_return(classes)
125
+ expect(Metasploit::ERD::Cluster).to receive(:new).with(*classes)
126
+
127
+ cluster
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,246 @@
1
+ require 'spec_helper'
2
+
3
+ describe Metasploit::ERD::Relationship do
4
+ include_context 'ActiveRecord::Base connection'
5
+ include_context 'ActiveRecord::Base.descendants cleaner'
6
+
7
+ subject(:relationship) {
8
+ described_class.new(association)
9
+ }
10
+
11
+ #
12
+ # lets
13
+ #
14
+
15
+ let(:owner) {
16
+ Class.new(ActiveRecord::Base)
17
+ }
18
+
19
+ let(:owner_name) {
20
+ 'Owner'
21
+ }
22
+
23
+ #
24
+ # Callbacks
25
+ #
26
+
27
+ before(:each) do
28
+ stub_const(owner_name, owner)
29
+ end
30
+
31
+ context '#class_set' do
32
+ subject(:class_set) {
33
+ relationship.class_set
34
+ }
35
+
36
+ context 'with polymorphic:' do
37
+ context 'false' do
38
+ let(:association) {
39
+ owner.reflect_on_association(:klass)
40
+ }
41
+
42
+ let(:klass) {
43
+ Class.new(ActiveRecord::Base)
44
+ }
45
+
46
+ let(:klass_name) {
47
+ 'Klass'
48
+ }
49
+
50
+ #
51
+ # Callbacks
52
+ #
53
+
54
+ before(:each) do
55
+ stub_const(klass_name, klass)
56
+
57
+ owner.belongs_to :klass,
58
+ class_name: klass_name,
59
+ inverse_of: :owneres
60
+
61
+ klass.has_many :owners,
62
+ class_name: 'Owner',
63
+ inverse_of: :klass
64
+
65
+ ActiveRecord::Migration.verbose = false
66
+
67
+ ActiveRecord::Migration.create_table :klasses do |t|
68
+ t.timestamps
69
+ end
70
+
71
+ ActiveRecord::Migration.create_table :owners do |t|
72
+ t.references :klass
73
+
74
+ t.timestamps
75
+ end
76
+ end
77
+
78
+ it { should be_a Set }
79
+
80
+ it 'includes association.klass' do
81
+ expect(class_set).to include(association.klass)
82
+ end
83
+ end
84
+
85
+ context 'true' do
86
+ #
87
+ # lets
88
+ #
89
+
90
+ let(:association) {
91
+ owner.reflect_on_association(:thing)
92
+ }
93
+
94
+ let(:things) {
95
+ owner_name = self.owner_name
96
+
97
+ thing_names.collect { |class_name|
98
+ klass = Class.new(ActiveRecord::Base) {
99
+ has_many :owners,
100
+ as: :thing,
101
+ class_name: owner_name
102
+ }
103
+
104
+ stub_const(class_name, klass)
105
+ }
106
+ }
107
+
108
+ let(:thing_names) {
109
+ Array.new(2) { |n|
110
+ "Thing#{n}"
111
+ }
112
+ }
113
+
114
+ #
115
+ # Callbacks
116
+ #
117
+
118
+ before(:each) do
119
+ owner.belongs_to :thing,
120
+ polymorphic: true
121
+
122
+ # ensure polymorphic target classes are created
123
+ things
124
+
125
+ ActiveRecord::Migration.verbose = false
126
+
127
+ ActiveRecord::Migration.create_table :owners do |t|
128
+ t.references :thing
129
+
130
+ t.timestamp
131
+ end
132
+
133
+ things.each do |thing|
134
+ ActiveRecord::Migration.create_table thing.table_name do |t|
135
+ t.timestamp
136
+ end
137
+ end
138
+ end
139
+
140
+ it { should be_a Set }
141
+
142
+ it 'includes all classes that have has_many <inverse>, as: <reflection.name>' do
143
+ expect(class_set).to eq(Set.new(things))
144
+ end
145
+
146
+ it 'calls #polymorphic_class_set' do
147
+ expect(relationship).to receive(:polymorphic_class_set)
148
+
149
+ class_set
150
+ end
151
+ end
152
+ end
153
+ end
154
+
155
+ context '#polymorphic_class_set' do
156
+ subject(:polymorphic_class_set) {
157
+ relationship.send(:polymorphic_class_set)
158
+ }
159
+
160
+ #
161
+ # Lets
162
+ #
163
+
164
+ let(:association) {
165
+ owner.reflect_on_association(:first)
166
+ }
167
+
168
+ let(:group_names) {
169
+ [
170
+ 'First',
171
+ 'Second'
172
+ ]
173
+ }
174
+
175
+ let(:polymorphics_by_group_name) {
176
+ owner_name = self.owner_name
177
+
178
+ polymorphic_names_by_group_name.each_with_object({}) { |(group_name, polymorphic_names), hash|
179
+ hash[group_name] = polymorphic_names.collect { |class_name|
180
+ klass = Class.new(ActiveRecord::Base) {
181
+ has_many :owners,
182
+ as: group_name.underscore.to_sym,
183
+ class_name: owner_name
184
+ }
185
+
186
+ stub_const(class_name, klass)
187
+ }
188
+ }
189
+ }
190
+
191
+ let(:polymorphic_names_by_group_name) {
192
+ group_names.each_with_object({}) { |group_name, hash|
193
+ hash[group_name] = Array.new(2) { |n|
194
+ "#{group_name}Polymorphic#{n}"
195
+ }
196
+ }
197
+ }
198
+
199
+ #
200
+ # Callbacks
201
+ #
202
+
203
+ before(:each) do
204
+ group_names.each do |group_name|
205
+ owner.belongs_to group_name.underscore.to_sym,
206
+ polymorphic: true
207
+ end
208
+
209
+ ActiveRecord::Migration.verbose = false
210
+
211
+ ActiveRecord::Migration.create_table :owners do |t|
212
+ group_names.each do |group_name|
213
+ t.references group_name.underscore.to_sym
214
+ end
215
+
216
+ t.timestamp
217
+ end
218
+
219
+ polymorphics_by_group_name.each do |group_name, polymorphics|
220
+ polymorphics.each do |klass|
221
+ ActiveRecord::Migration.create_table klass.table_name do |t|
222
+ t.timestamps
223
+ end
224
+ end
225
+ end
226
+ end
227
+
228
+ it { should be_a Set }
229
+
230
+ context 'with has_many as: <association.name>' do
231
+ it 'includes classes' do
232
+ polymorphics_by_group_name['First'].each do |klass|
233
+ expect(polymorphic_class_set).to include(klass)
234
+ end
235
+ end
236
+ end
237
+
238
+ context 'with has_many as: <not association.name>' do
239
+ it 'does not include classes' do
240
+ polymorphics_by_group_name['Second'].each do |klass|
241
+ expect(polymorphic_class_set).not_to include(klass)
242
+ end
243
+ end
244
+ end
245
+ end
246
+ end
@@ -0,0 +1,125 @@
1
+ require 'spec_helper'
2
+
3
+ require 'active_support/core_ext/object/blank'
4
+
5
+ describe Metasploit::ERD::Version do
6
+ context 'CONSTANTS' do
7
+ context 'MAJOR' do
8
+ subject(:major) do
9
+ described_class::MAJOR
10
+ end
11
+
12
+ it 'is 0 because the API is not locked yet' do
13
+ expect(major).to eq(0)
14
+ end
15
+ end
16
+
17
+ context 'MINOR' do
18
+ subject(:minor) do
19
+ described_class::MINOR
20
+ end
21
+
22
+ it { should be_a Integer }
23
+ end
24
+
25
+ context 'PATCH' do
26
+ subject(:patch) do
27
+ described_class::PATCH
28
+ end
29
+
30
+ it { should be_a Integer }
31
+ end
32
+
33
+ pull_request = ENV['TRAVIS_PULL_REQUEST']
34
+
35
+ # a pull request cannot check PRERELEASE because it will be tested in the target branch, but the source itself
36
+ # is from the source branch and so has the source branch PRERELEASE.
37
+ #
38
+ # PRERELEASE can only be set appropriately for a merge by merging to the target branch and then updating PRERELEASE
39
+ # on the target branch before committing and/or pushing to github and travis-ci.
40
+ if pull_request.nil? || pull_request == 'false'
41
+ context 'PREPRELEASE' do
42
+ subject(:prerelease) do
43
+ described_class::PRERELEASE
44
+ end
45
+
46
+ branch = ENV['TRAVIS_BRANCH']
47
+
48
+ if branch.blank?
49
+ branch = `git rev-parse --abbrev-ref HEAD`.strip
50
+ end
51
+
52
+ if branch == 'master'
53
+ it 'does not have a PRERELEASE' do
54
+ expect(defined? described_class::PRERELEASE).to be_nil
55
+ end
56
+ else
57
+ feature_regex = /(feature|staging)\/(?<prerelease>.*)/
58
+ match = branch.match(feature_regex)
59
+
60
+ if match
61
+ it 'matches the branch relative name' do
62
+ expect(prerelease).to eq(match[:prerelease])
63
+ end
64
+ else
65
+ it 'has a abbreviated reference that can be parsed for prerelease' do
66
+ fail "Do not know how to parse #{branch.inspect} for PRERELEASE"
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ context 'full' do
75
+ subject(:full) do
76
+ described_class.full
77
+ end
78
+
79
+ #
80
+ # lets
81
+ #
82
+
83
+ let(:major) do
84
+ 1
85
+ end
86
+
87
+ let(:minor) do
88
+ 2
89
+ end
90
+
91
+ let(:patch) do
92
+ 3
93
+ end
94
+
95
+ before(:each) do
96
+ stub_const("#{described_class}::MAJOR", major)
97
+ stub_const("#{described_class}::MINOR", minor)
98
+ stub_const("#{described_class}::PATCH", patch)
99
+ end
100
+
101
+ context 'with PRERELEASE' do
102
+ let(:prerelease) do
103
+ 'prerelease'
104
+ end
105
+
106
+ before(:each) do
107
+ stub_const("#{described_class}::PRERELEASE", prerelease)
108
+ end
109
+
110
+ it 'is <major>.<minor>.<patch>-<prerelease>' do
111
+ expect(full).to eq("#{major}.#{minor}.#{patch}-#{prerelease}")
112
+ end
113
+ end
114
+
115
+ context 'without PRERELEASE' do
116
+ before(:each) do
117
+ hide_const("#{described_class}::PRERELEASE")
118
+ end
119
+
120
+ it 'is <major>.<minor>.<patch>' do
121
+ expect(full).to eq("#{major}.#{minor}.#{patch}")
122
+ end
123
+ end
124
+ end
125
+ end