metasploit-erd 0.0.1

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