hirsute 0.1.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,8 @@
1
+ Derrick
2
+ Melissa
3
+ Sam
4
+ Robert
5
+ Camille
6
+ Britney
7
+ Zelda
8
+ Steve
@@ -0,0 +1,362 @@
1
+ # unit tests for the hirsute language
2
+
3
+ require 'test/unit'
4
+ require 'lib/hirsute_utils.rb'
5
+ require 'lib/hirsute.rb'
6
+ require 'lib/hirsute_make_generators.rb'
7
+ require 'lib/hirsute_collection.rb'
8
+
9
+ class TestHirsute < Test::Unit::TestCase
10
+ include Hirsute::GeneratorMakers
11
+ include Hirsute::Support
12
+
13
+ # test functionality of the histogram distribution
14
+ def testIntegerFromHistogram1
15
+
16
+ # define a very skewed histogram
17
+ histogram_a = [0.9,0.05,0.05]
18
+ values_a = Array.new(histogram_a.length,0)
19
+
20
+ (1..1000).each do |i|
21
+ index = integer_from_histogram(histogram_a)
22
+ values_a[index] = values_a[index] + 1
23
+ end
24
+
25
+ # check for 5% tolerance
26
+ assert(values_a[0] > 855 && values_a[0] < 945)
27
+
28
+ end
29
+
30
+ def testHistogramGreaterThanList
31
+ begin
32
+ random_item_with_histogram([1,2],[1,2,3,4])
33
+ fail
34
+ rescue Exception => e
35
+ assert(true)
36
+ end
37
+ end
38
+
39
+ def testHistogramDoesntEqualOne
40
+ histogram = [0.2,0.1]
41
+ values = Array.new
42
+
43
+ (1..1000).each do |i|
44
+ values << random_item_with_histogram([1,2],histogram)
45
+ end
46
+
47
+ one_values = values.select {|item| item == 1}
48
+ two_values = values.select {|item| item == 2}
49
+
50
+ assert(one_values.length > 667 * 0.95 && one_values.length < 667 * 1.05)
51
+ assert(two_values.length > 333 * 0.95 && two_values.length < 333 * 1.05)
52
+ end
53
+
54
+ def testOneOfWithHistogram
55
+ results = []
56
+ list = ["a","b","c"]
57
+ histogram = [0.9,0.05,0.05]
58
+ gen = one_of(list,histogram)
59
+ (1..1000).each do |i|
60
+ results << gen.generate(nil)
61
+ end
62
+
63
+ a_count = (results.select {|item| item == 'a'}).length
64
+ assert(a_count > 855 && a_count < 945)
65
+ end
66
+
67
+ def testGeneratorBlockRunWithinInstance
68
+ template = make_template("testGeneratorBlockRunWithinInstance") {
69
+ has :id => counter(3),
70
+ :triple => depending_on(:id,
71
+ Hirsute::DEFAULT => "") {|result| id * 3}
72
+ }
73
+ obj = template.make
74
+ assert(obj.triple == (obj.id * 3))
75
+ end
76
+
77
+
78
+ def testOneOfGenerator
79
+
80
+ domains = ["gmail.com","yahoo.com","ea.com"]
81
+ domain = one_of(domains).generate(nil)
82
+ assert(domain == 'gmail.com' || domain == 'yahoo.com' || domain = 'ea.com')
83
+ end
84
+
85
+ def testFileRead
86
+ gen = read_from_file('tests/first_names.txt',:linear)
87
+ line = gen.generate(nil)
88
+ assert(line == 'Derrick')
89
+
90
+ # toss the rest
91
+ (1..7).each do |i|
92
+ line = gen.generate(nil)
93
+ end
94
+
95
+ line = gen.generate(nil) # should have wrapped around
96
+ assert(line == 'Derrick')
97
+ end
98
+
99
+ def testCollectionCreationWithObject
100
+ coll = Hirsute::Collection.new("String")
101
+ begin
102
+ coll << 3
103
+ flunk "Collection should not allow an inconsistent type"
104
+ rescue Exception => e
105
+ assert(coll.length == 0)
106
+ end
107
+ end
108
+
109
+ def testCollectionCreationWithoutObject
110
+ coll = Hirsute::Collection.new('fixnum')
111
+ coll << 3
112
+ begin
113
+ coll << "test"
114
+ flunk "Strings should not be allowed in a collection created as an integer"
115
+ rescue
116
+ assert(coll.length == 1)
117
+ end
118
+ end
119
+
120
+ def testCollectionChoice
121
+ coll = Hirsute::Collection.new("String")
122
+ coll << "a"
123
+ coll << "b"
124
+ coll << "c"
125
+
126
+ str = one_of(coll).generate(nil)
127
+ assert(str=='a' || str == 'b' || str == 'c')
128
+ end
129
+
130
+ def testPostGenerateBlockExecution
131
+ list = ['abc','apple','asparagus']
132
+ gen = one_of(list) {|value| value[0,1]}
133
+ result = gen.generate(nil)
134
+ assert(result == 'a')
135
+ end
136
+
137
+ # ensure that when you create a collection for an object, that it registers itself as a holder of that object type
138
+ def testCollectionsRegisterForObject
139
+ objName = 'testObj'
140
+
141
+ #setup, copied from hirsute.rb
142
+ objClass = Class.new(Hirsute::Fixed)
143
+ objClassName = Kernel.const_set(objName.capitalize.to_sym,objClass)
144
+
145
+ template = Hirsute::Template.new(objName)
146
+
147
+ coll1 = template * 2
148
+ coll2 = template * 3
149
+ all_colls = Hirsute::Collection.collections_holding_object(objName)
150
+ assert(all_colls.length == 2)
151
+ end
152
+
153
+ # tests that is_template works
154
+ def testIsTemplate
155
+ testObj2 = Hirsute::Template.new('testObj2')
156
+ assert(is_template(testObj2))
157
+ end
158
+
159
+ def testCollectionRejectsDifferentObject
160
+ template1 = make_template('testCollectionRejectsDifferentObject1')
161
+ template2 = make_template('testCollectionRejectsDifferentObject2')
162
+
163
+ coll1 = template1 * 2
164
+
165
+ begin
166
+ coll1 << template2
167
+ assert(false)
168
+ rescue
169
+ assert(true)
170
+ end
171
+ end
172
+
173
+ def testMakeAddsToSingleCollection
174
+ template = make_template('testMakeAddsToSingleCollection')
175
+ coll = collection_of template
176
+ template.make
177
+ assert(coll.length == 1)
178
+ end
179
+
180
+
181
+ # ensure that the << operator works properly when appending a template (i.e., it makes a new object rather than appending the template)
182
+ def testAppendWithTemplate
183
+ testObj3 = make_template('testObj3') {
184
+ has :id => counter(1)
185
+ }
186
+
187
+ coll = testObj3 * 1
188
+ coll << testObj3
189
+
190
+ # either line would have raised an exception if the collection thought it was an invalid type (see test above)
191
+ assert(true)
192
+ end
193
+
194
+ def testNestedGenerators
195
+ template = make_template('testNestedGenerators') {
196
+ has :id => one_of([one_of([1,2,3]),one_of([4,5,6])])
197
+ }
198
+ obj = template.make
199
+ assert(obj.id == 1 || obj.id == 2 || obj.id == 3 || obj.id == 4 || obj.id == 5 || obj.id == 6)
200
+ end
201
+
202
+ def testSubset
203
+ template = make_template('testSubset') {
204
+ has :item => subset(one_of([1,2,3]),
205
+ one_of(['a','b','c']),
206
+ one_of([4,5,6]))
207
+ }
208
+ obj = template.make
209
+ assert(obj.item.length <= 3 && obj.item.length > 0)
210
+ end
211
+
212
+ def testAppendCollectionToCollection
213
+ template = make_template('testAppendCollectionToCollection')
214
+ coll1 = template * 3
215
+ coll2 = template * 4
216
+ coll1 << coll2
217
+ assert(coll1.length == 7)
218
+ end
219
+
220
+ def testAnyObject
221
+ template = make_template('testAnyObject') {
222
+ has :objid => counter(1)
223
+ }
224
+ coll1 = template * 3
225
+ coll2 = template * 4
226
+ greaterThan5 = any(template) {|item| item.objid > 5}
227
+ assert(greaterThan5.objid > 5)
228
+
229
+ equals2 = any(template) do |item|
230
+ item.objid == 2
231
+ end
232
+ assert(equals2.objid == 2)
233
+ end
234
+
235
+ def testReadFromSequence
236
+ template = make_template('testReadFromSequence') {
237
+ has :looper => read_from_sequence([1,2,3,4])
238
+ }
239
+
240
+ # 5 objects should exercise the loop of 4 items
241
+ template1 = template.make
242
+ template2 = template.make
243
+ template3 = template.make
244
+ template4 = template.make
245
+ template5 = template.make
246
+
247
+ assert(template4.looper == 4)
248
+ assert(template5.looper == template1.looper)
249
+
250
+ end
251
+
252
+ def testDependentGeneratorCircularDependencyException
253
+ template = make_template("testDependentGeneratorCircularDependencyException") {
254
+ has :a => depending_on(:b, 3 => 3),
255
+ :b => depending_on(:a, 4 => 4)
256
+ }
257
+ begin
258
+ template.make
259
+ fail
260
+ rescue
261
+ assert(true)
262
+ end
263
+ end
264
+
265
+ def testDependencyBasics
266
+ template = make_template("testDependencyBasics") {
267
+ has :value => read_from_sequence([1,2,3]),
268
+ :name => depending_on(:value,
269
+ 1 => 'a')
270
+ }
271
+ template1 = template.make
272
+ template2 = template.make
273
+ assert(template1.name == 'a')
274
+ assert(template2.name.nil?)
275
+ end
276
+
277
+ def testDependencyBasicsWithDefault
278
+ template = make_template("testDependencyBasicsWithDefault") {
279
+ has :value => read_from_sequence([1,2,3]),
280
+ :name => depending_on(:value,
281
+ 1 => 'a',
282
+ Hirsute::DEFAULT => 'z')
283
+ }
284
+
285
+ template1 = template.make
286
+ template2 = template.make
287
+ template3 = template.make
288
+
289
+ assert(template1.value == 1 && template1.name == 'a')
290
+ assert(template2.value == 2 && template2.name == 'z')
291
+ assert(template3.value == 3 && template3.name == 'z')
292
+ end
293
+
294
+ def testRequiresField
295
+ template = make_template("testRequiresField") {
296
+ has :value => requires_field(:literal,counter(20)) {|value| self.literal = value},
297
+ :literal => 1
298
+ }
299
+
300
+ template1 = template.make
301
+ assert(template1.literal == template1.value)
302
+ end
303
+
304
+ def testRangeArrayCaching
305
+ range1 = 1..3
306
+ range2 = 1..3 # ensure that the same conceptual range maps to the same array
307
+
308
+ range3 = 1..4
309
+
310
+ ary = Hirsute::Support.get_range_array(range1)
311
+ ary2 = Hirsute::Support.get_range_array(range2)
312
+ ary3 = Hirsute::Support.get_range_array(range2)
313
+ ary4 = Hirsute::Support.get_range_array(range3)
314
+ assert(ary.equal?(ary2))
315
+ assert(ary.equal?(ary3))
316
+ assert(!ary.equal?(ary4))
317
+ end
318
+
319
+ def testRangeResultsBecomeElements
320
+ template = make_template("testRangeResultsBecomeElements") {
321
+ has :rating => one_of([1..10])
322
+ }
323
+ obj = template.make
324
+ assert(obj.rating >= 1 && obj.rating <= 10)
325
+ end
326
+
327
+ # just to measure that range caching is worth it
328
+ def testRangeCachingSpeed
329
+ iterations = 100000
330
+ range = 1..10
331
+
332
+ start = Time.new
333
+ (1..iterations).each {|i| range.to_a}
334
+
335
+ avg_to_a_time = (Time.new - start).to_f / iterations
336
+
337
+ start = Time.new
338
+ (1..iterations).each {|i| Hirsute::Support.get_range_array(range)}
339
+ avg_cached_time = (Time.new - start).to_f / iterations
340
+
341
+ assert(avg_cached_time < avg_to_a_time)
342
+
343
+ end
344
+
345
+ # for testing outputter behavior.
346
+ class TestOutputter < Hirsute::Outputter
347
+ def _outputItem(item)
348
+ end
349
+ end
350
+
351
+ def testFieldsInOutputter
352
+ # build up the collection
353
+ template = make_template("testFieldsInOutputter") {
354
+ has :id => counter(1)
355
+ }
356
+ collection = template * 4
357
+
358
+ outputter = TestOutputter.new(collection)
359
+ assert(outputter.fields[0] == :id)
360
+ end
361
+
362
+ end
@@ -0,0 +1,32 @@
1
+ # unit tests for the histoparse subsystem of Hirsute
2
+ require 'test/unit'
3
+ require 'lib/histoparse.rb'
4
+
5
+ class TestHistoParse < Test::Unit::TestCase
6
+
7
+ include Hirsute::HistoParse
8
+
9
+ def testBasicParsing
10
+ histogram = <<-HIST
11
+ **
12
+
13
+ ****
14
+
15
+ | **
16
+ | *
17
+ | *
18
+ HIST
19
+
20
+ parsed_histogram = parse_histogram(histogram)
21
+ buckets = parsed_histogram.histogram_buckets
22
+ assert(!buckets.nil?)
23
+
24
+ assert(buckets[0] > 0.19 && buckets[0] < 0.21)
25
+ assert(buckets[1] > 0.39 && buckets[1] < 0.41)
26
+ assert(buckets[2] > 0.19 && buckets[2] < 0.21)
27
+ assert(buckets[3] > 0.09 && buckets[3] < 0.11)
28
+ assert(buckets[4] > 0.09 && buckets[4] < 0.11)
29
+
30
+ end
31
+
32
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hirsute
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Derrick Schneider
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2013-06-02 00:00:00 Z
13
+ dependencies: []
14
+
15
+ description: " Hirsute is a Ruby-based domain specific language for creating\n fake data based on a variety of techniques, including non-uniform\n probabilities to more closely emulate real-world data.\n (e.g., allow a person to have up to 100 friends in a social\n network but specify that most will have between ten and twenty.)\n"
16
+ email: derrick.schneider@gmail.com
17
+ executables:
18
+ - hirsute
19
+ extensions: []
20
+
21
+ extra_rdoc_files: []
22
+
23
+ files:
24
+ - ./lib/hirsute.rb
25
+ - ./lib/hirsute_collection.rb
26
+ - ./lib/hirsute_constraint.rb
27
+ - ./lib/hirsute_fixed.rb
28
+ - ./lib/hirsute_generator.rb
29
+ - ./lib/hirsute_make_generators.rb
30
+ - ./lib/hirsute_output.rb
31
+ - ./lib/hirsute_template.rb
32
+ - ./lib/hirsute_test.rb
33
+ - ./lib/hirsute_utils.rb
34
+ - ./lib/histoparse.rb
35
+ - ./tests/hirsute_test.rb
36
+ - ./tests/histoparse_test.rb
37
+ - ./manual.md
38
+ - ./README.md
39
+ - ./samples/readme.hrs
40
+ - ./samples/wine_cellar.hrs
41
+ - ./bin/hirsute
42
+ - ./tests/first_names.txt
43
+ - ./MIT_LICENSE
44
+ - bin/hirsute
45
+ homepage:
46
+ licenses: []
47
+
48
+ metadata: {}
49
+
50
+ post_install_message:
51
+ rdoc_options: []
52
+
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - &id001
58
+ - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - *id001
64
+ requirements: []
65
+
66
+ rubyforge_project:
67
+ rubygems_version: 2.0.3
68
+ signing_key:
69
+ specification_version: 4
70
+ summary: A DSL for creating fake but plausible data.
71
+ test_files: []
72
+