icss 0.1.3 → 0.3.2
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.
- data/.watchr +35 -3
- data/CHANGELOG.md +38 -0
- data/Gemfile +19 -14
- data/README.md +296 -0
- data/Rakefile +2 -6
- data/TODO.md +13 -0
- data/VERSION +1 -1
- data/examples/avro_examples/complicated.icss.yaml +14 -13
- data/examples/bnc.icss.yaml +70 -0
- data/examples/chronic.icss.yaml +3 -3
- data/examples/license.icss.yaml +7 -0
- data/examples/source1.icss.yaml +4 -0
- data/examples/source2.icss.yaml +4 -0
- data/examples/test_icss.yaml +67 -0
- data/icss.gemspec +103 -43
- data/lib/icss.rb +37 -15
- data/lib/icss/core_types.rb +19 -0
- data/lib/icss/error.rb +4 -0
- data/{init.rb → lib/icss/init.rb} +0 -0
- data/lib/icss/message.rb +124 -66
- data/lib/icss/message/message_sample.rb +144 -0
- data/lib/icss/protocol.rb +184 -131
- data/lib/icss/protocol/code_asset.rb +18 -0
- data/lib/icss/protocol/data_asset.rb +23 -0
- data/lib/icss/protocol/license.rb +41 -0
- data/lib/icss/protocol/source.rb +37 -0
- data/lib/icss/protocol/target.rb +68 -0
- data/lib/icss/receiver_model.rb +24 -0
- data/lib/icss/receiver_model/active_model_shim.rb +36 -0
- data/lib/icss/receiver_model/acts_as_catalog.rb +170 -0
- data/lib/icss/receiver_model/acts_as_hash.rb +177 -0
- data/lib/icss/receiver_model/acts_as_loadable.rb +47 -0
- data/lib/icss/receiver_model/acts_as_tuple.rb +100 -0
- data/lib/icss/receiver_model/locale/en.yml +27 -0
- data/lib/icss/receiver_model/to_geo_json.rb +19 -0
- data/lib/icss/receiver_model/tree_merge.rb +34 -0
- data/lib/icss/receiver_model/validations.rb +31 -0
- data/lib/icss/serialization.rb +51 -0
- data/lib/icss/serialization/zaml.rb +443 -0
- data/lib/icss/type.rb +148 -501
- data/lib/icss/type/base_type.rb +0 -0
- data/lib/icss/type/named_type.rb +184 -0
- data/lib/icss/type/record_field.rb +77 -0
- data/lib/icss/type/record_model.rb +49 -0
- data/lib/icss/type/record_schema.rb +54 -0
- data/lib/icss/type/record_type.rb +325 -0
- data/lib/icss/type/simple_types.rb +72 -0
- data/lib/icss/type/structured_schema.rb +288 -0
- data/lib/icss/type/type_factory.rb +144 -0
- data/lib/icss/type/union_schema.rb +41 -0
- data/lib/icss/view_helper.rb +56 -19
- data/notes/named_array.md +32 -0
- data/notes/on_include_vs_extend_etc.rb +176 -0
- data/notes/technical_details.md +278 -0
- data/spec/core_types_spec.rb +119 -0
- data/spec/fixtures/zaml_complex_hash.yaml +35 -0
- data/spec/icss_spec.rb +86 -23
- data/spec/message/message_sample_spec.rb +4 -0
- data/spec/message_spec.rb +139 -0
- data/spec/protocol/license_spec.rb +67 -0
- data/spec/protocol/protocol_catalog_spec.rb +48 -0
- data/spec/protocol/protocol_validations_spec.rb +176 -0
- data/spec/protocol/source_spec.rb +65 -0
- data/spec/protocol_spec.rb +91 -37
- data/spec/receiver_model_spec.rb +111 -0
- data/spec/serialization/zaml_spec.rb +81 -0
- data/spec/serialization/zaml_test.rb +473 -0
- data/spec/serialization_spec.rb +63 -0
- data/spec/spec_helper.rb +24 -7
- data/spec/support/icss_test_helper.rb +67 -0
- data/spec/support/load_example_protocols.rb +17 -0
- data/spec/type/base_type_spec.rb +0 -0
- data/spec/type/named_type_spec.rb +75 -0
- data/spec/type/record_field_spec.rb +44 -0
- data/spec/type/record_model_spec.rb +206 -0
- data/spec/type/record_schema_spec.rb +161 -0
- data/spec/type/record_type_spec.rb +155 -0
- data/spec/type/simple_types_spec.rb +121 -0
- data/spec/type/structured_schema_spec.rb +300 -0
- data/spec/type/type_catalog_spec.rb +44 -0
- data/spec/type/type_factory_spec.rb +93 -0
- data/spec/type/union_schema_spec.rb +0 -0
- data/spec/type_spec.rb +63 -0
- metadata +205 -144
- data/CHANGELOG.textile +0 -9
- data/Gemfile.lock +0 -40
- data/README.textile +0 -29
- data/lib/icss/brevity.rb +0 -136
- data/lib/icss/code_asset.rb +0 -16
- data/lib/icss/core_ext.rb +0 -9
- data/lib/icss/data_asset.rb +0 -22
- data/lib/icss/old.rb +0 -96
- data/lib/icss/protocol_set.rb +0 -48
- data/lib/icss/sample_message_call.rb +0 -142
- data/lib/icss/target.rb +0 -72
- data/lib/icss/type/factory.rb +0 -196
- data/lib/icss/validations.rb +0 -16
- data/spec/validations_spec.rb +0 -171
@@ -0,0 +1,111 @@
|
|
1
|
+
require File.expand_path('spec_helper', File.dirname(__FILE__))
|
2
|
+
require 'icss'
|
3
|
+
require ENV.root_path('spec/support/icss_test_helper')
|
4
|
+
include IcssTestHelper
|
5
|
+
|
6
|
+
describe Icss::ReceiverModel do
|
7
|
+
before do
|
8
|
+
IcssTestHelper.remove_icss_constants('Handy', 'UnderHandy')
|
9
|
+
class Icss::Handy < Icss::SmurfModel ; end
|
10
|
+
class Icss::UnderHandy < Icss::Handy ; end
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'field validations' do
|
14
|
+
before do
|
15
|
+
Icss::Handy.field :rangey, Integer, :validates => { :inclusion => { :in => 0..9 }}
|
16
|
+
Icss::Handy.field :mandatory, Integer, :validates => { :presence => true }
|
17
|
+
Icss::Handy.field :patternish, String, :validates => { :format => { :with => /eat$/ } }
|
18
|
+
end
|
19
|
+
let(:good_smurf){ Icss::Handy.receive(:rangey => 5, :patternish => 'smurfberry crunch is fun to eat', :mandatory => 1) }
|
20
|
+
let(:bad_smurf ){ Icss::Handy.receive(:rangey => 10, :patternish => 'smurfnuggets!') }
|
21
|
+
|
22
|
+
it 'are applied, and pass when good' do
|
23
|
+
good_smurf.should be_valid
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'are applied, and fail when bad' do
|
27
|
+
bad_smurf.should_not be_valid
|
28
|
+
bad_smurf.errors.should == {
|
29
|
+
:rangey => ["is not included in the list"],
|
30
|
+
:mandatory => ["can't be blank"],
|
31
|
+
:patternish => ["is invalid"]
|
32
|
+
}
|
33
|
+
bad_smurf.rangey = 3 ; bad_smurf.mandatory = 7 ; bad_smurf.patternish = "a very smurfy breakfast treat"
|
34
|
+
bad_smurf.should be_valid
|
35
|
+
bad_smurf.errors.should be_empty
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'inherit' do
|
39
|
+
under_handy = Icss::UnderHandy.receive(:rangey => -1, :patternish => 'smurfberry crunch is fun to eat', :mandatory => 1)
|
40
|
+
under_handy.should_not be_valid
|
41
|
+
under_handy.errors.keys.should == [:rangey]
|
42
|
+
under_handy.rangey = 1
|
43
|
+
under_handy.should be_valid
|
44
|
+
end
|
45
|
+
|
46
|
+
it ':required => true is sugar for ":validates => { :presence => true }"' do
|
47
|
+
Icss::Handy.field :also_mandatory, Integer, :required => true
|
48
|
+
good_smurf.should_not be_valid
|
49
|
+
good_smurf.errors.should == { :also_mandatory => ["can't be blank"], }
|
50
|
+
good_smurf.also_mandatory = 88
|
51
|
+
good_smurf.should be_valid
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# context ':index => ' do
|
56
|
+
# it 'primary key'
|
57
|
+
# it 'foreign key'
|
58
|
+
# it 'uniqueness constraint'
|
59
|
+
# end
|
60
|
+
#
|
61
|
+
# # context ':accessor / :reader / :writer' do
|
62
|
+
# # it ':private -- attr_whatever is private'
|
63
|
+
# # it ':protected -- attr_whatever is protected'
|
64
|
+
# # it ':none -- no accessor/reader/writer'
|
65
|
+
# # end
|
66
|
+
#
|
67
|
+
# context ':after_receive'
|
68
|
+
#
|
69
|
+
# context ':i18n_key'
|
70
|
+
# context ':human_name => '
|
71
|
+
# context ':singular_name => '
|
72
|
+
# context ':plural_name => '
|
73
|
+
# context ':uncountable => '
|
74
|
+
#
|
75
|
+
# context :serialization
|
76
|
+
# it '#serializable_hash'
|
77
|
+
#
|
78
|
+
# # constant
|
79
|
+
# # mass assignment security: accessible,
|
80
|
+
#
|
81
|
+
# it 'works on the parent Meta module type, not '
|
82
|
+
#
|
83
|
+
#
|
84
|
+
# context 'has properties' do
|
85
|
+
# it 'described by its #fields'
|
86
|
+
#
|
87
|
+
# context 'container types' do
|
88
|
+
#
|
89
|
+
# it 'field foo, Array, :items => FooClass validates instances are is_a?(FooClass)'
|
90
|
+
# it 'field foo, Array, :with => FooFactory validates instances are is_a?(FooFactory.product_klass)'
|
91
|
+
#
|
92
|
+
# it ''
|
93
|
+
#
|
94
|
+
# end
|
95
|
+
# end
|
96
|
+
#
|
97
|
+
# context 'special properties' do
|
98
|
+
# it '_domain_id_field'
|
99
|
+
# it '_primary_location_field'
|
100
|
+
# it '_slug' # ??
|
101
|
+
# end
|
102
|
+
#
|
103
|
+
# context 'name' do
|
104
|
+
# context ':i18n_key'
|
105
|
+
# context ':human_name => '
|
106
|
+
# context ':singular_name => '
|
107
|
+
# context ':plural_name => '
|
108
|
+
# context ':uncountable => '
|
109
|
+
# end
|
110
|
+
|
111
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
3
|
+
require 'yaml'
|
4
|
+
require 'icss/serialization/zaml'
|
5
|
+
|
6
|
+
describe ZAML do
|
7
|
+
describe '#to_zaml' do
|
8
|
+
[nil, :my_sym, true, false, 69, 69.0, /my_regexp/,
|
9
|
+
ArgumentError.new('my_exception'),
|
10
|
+
'my_str',
|
11
|
+
{'simple' => :hash, :items => {2 => /pairs/}},
|
12
|
+
['arr', :items, 4, /things/], Time.now, (3..69),
|
13
|
+
].each do |obj|
|
14
|
+
it "serializes a #{obj.class}" do
|
15
|
+
obj.to_zaml.should == obj.to_yaml
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
BASIC_HASH = {
|
21
|
+
:name => "a few",
|
22
|
+
:nested => "elements",
|
23
|
+
:including => "line\nbreaking\nstrings",
|
24
|
+
:and_including => "newline terminated\nline\nbreaking\nstrings\n",
|
25
|
+
:so => ":what
|
26
|
+
:dyathink, :of, :that
|
27
|
+
"
|
28
|
+
}
|
29
|
+
|
30
|
+
def complex_hash
|
31
|
+
{ 'complex' => :hash,
|
32
|
+
:items => {2 => /pairs/},
|
33
|
+
'Iñtërnâtiônàlizætiøn' => "look out for 'funny quotes'.",
|
34
|
+
:and => [BASIC_HASH, { :name => 'bob' }, [], ],
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def complex_hash_with_comments
|
39
|
+
{
|
40
|
+
ZAML::Comment.new("first comment") => 1,
|
41
|
+
'complex' => :hash,
|
42
|
+
:items => {2 => /pairs/},
|
43
|
+
'Iñtërnâtiônàlizætiøn' => "look out for 'funny quotes'.",
|
44
|
+
:and => [
|
45
|
+
ZAML::Comment.new("informative comments"),
|
46
|
+
BASIC_HASH,
|
47
|
+
ZAML::Comment.new("more informative comments, \nspread across\n multiple lines"),
|
48
|
+
{
|
49
|
+
:name => 'bob',
|
50
|
+
ZAML::Comment.new("comment can be in hash key, \nspread across\n multiple lines;") => :zaml_ignores_their_hash_val
|
51
|
+
},
|
52
|
+
ZAML.padding(3),
|
53
|
+
[ZAML::Comment.new("does the right thing \neven when\nis the only item")],
|
54
|
+
],
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'valign' do
|
59
|
+
it 'accepts an option, defaults to nil' do
|
60
|
+
obj = ZAML.new(:valign => 24)
|
61
|
+
obj.valign.should == 24
|
62
|
+
obj = ZAML.new()
|
63
|
+
obj.valign.should == nil
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'aligns things' do
|
67
|
+
obj = complex_hash_with_comments
|
68
|
+
yaml_str = ZAML.dump(obj, '', :valign => 24 )
|
69
|
+
# puts yaml_str
|
70
|
+
from_yaml = YAML.load(yaml_str)
|
71
|
+
from_yaml.should == complex_hash
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'matches sample' do
|
75
|
+
expected_yaml_str = File.read(ENV.root_path('spec/fixtures/zaml_complex_hash.yaml'))
|
76
|
+
yaml_str = ZAML.dump(complex_hash_with_comments, '', :valign => 24 )
|
77
|
+
# puts yaml_str
|
78
|
+
yaml_str.should == expected_yaml_str
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,473 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- encoding: utf-8 -*-
|
3
|
+
|
4
|
+
require 'test/unit'
|
5
|
+
require 'yaml'
|
6
|
+
|
7
|
+
$LOAD_PATH.unshift(File.expand_path('../../lib', File.dirname(__FILE__)))
|
8
|
+
require 'icss/serialization/zaml'
|
9
|
+
|
10
|
+
DICT_WORDS_PATH = '/usr/share/dict/words'
|
11
|
+
SLOWNESS = 0 # how acceptably slow are you willing to have the tests take
|
12
|
+
|
13
|
+
ENCODING_KLUDGE = true # YAML loads in UTF-8, causing strings to compare unequal
|
14
|
+
INDENTED_ARRAYS_KLUDGE = true # YAML is uglier about indenting arrays under hashes
|
15
|
+
YAML_DUPS_STRINGS_KLUDGE = true # YAML in 1.9 is less aggressive about referencing strings
|
16
|
+
|
17
|
+
class My_class
|
18
|
+
def initialize
|
19
|
+
@string = 'string...'
|
20
|
+
@self = self
|
21
|
+
@do_not_store_me = '*************** SHOULD NOT SHOW UP IN OUTPUT ***************'
|
22
|
+
end
|
23
|
+
def to_yaml_properties
|
24
|
+
['@string', '@self']
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class ZamlDumpTest < Test::Unit::TestCase
|
29
|
+
#
|
30
|
+
# This class and the test helper which follow embody what we mean by YAML compatibility.
|
31
|
+
# When we do a round-trip dump->load we expect
|
32
|
+
# 1) that the data from ZAML.dump will come back correctly
|
33
|
+
# 1a) all vales will be correct
|
34
|
+
# 1b) only data that should be dumped is
|
35
|
+
# 1c) object identity is preseved
|
36
|
+
# 2) if YAML.dump also works by these standards the dumped data should
|
37
|
+
# generally look like what yaml.rb produces, minus unneeded whitespace
|
38
|
+
# (trailing blanks, etc.)
|
39
|
+
class Equivalency < Hash
|
40
|
+
attr_reader :result,:message
|
41
|
+
|
42
|
+
def self.test(a,b)
|
43
|
+
new.test(a,b)
|
44
|
+
end
|
45
|
+
def test(a,b)
|
46
|
+
@result = equivalent(a,b)
|
47
|
+
self
|
48
|
+
end
|
49
|
+
def note_failure(msg)
|
50
|
+
(@message ||= '') << msg
|
51
|
+
false
|
52
|
+
end
|
53
|
+
def same_class(a,b)
|
54
|
+
(a.class == b.class) or note_failure("Saw a #{a.class} but expected a #{b.class}\n")
|
55
|
+
end
|
56
|
+
def seen_either_before(a,b)
|
57
|
+
result = (has_key?(a.object_id) or has_key?(b.object_id))
|
58
|
+
(self[a.object_id] = self[b.object_id] = size) unless result or a.is_a? Numeric
|
59
|
+
result
|
60
|
+
end
|
61
|
+
def matched_before(a,b)
|
62
|
+
(self[a.object_id] == self[b.object_id]) or note_failure("#{a.inspect} [#{a.object_id}] and #{b.inspect} [#{b.object_id}] should refer to the same object.\n")
|
63
|
+
end
|
64
|
+
def same_object(a,b)
|
65
|
+
a.object_id == b.object_id
|
66
|
+
end
|
67
|
+
|
68
|
+
def guess_mapping(a,b)
|
69
|
+
result = {}
|
70
|
+
a.delete_if{|xa| result[xa] = b.delete(xa) }
|
71
|
+
raise "Too many odd keys in a test hash to tell if the results are correct." if a.length > 1
|
72
|
+
a.each {|xa| result[xa] = b.pop }
|
73
|
+
result
|
74
|
+
end
|
75
|
+
def same_properties(a,b)
|
76
|
+
@what_we_are_looking_at ||= []
|
77
|
+
return true if @what_we_are_looking_at.include? [a.object_id,b.object_id]
|
78
|
+
@what_we_are_looking_at.push [a.object_id,b.object_id]
|
79
|
+
result =
|
80
|
+
case a
|
81
|
+
when Array
|
82
|
+
(a.length == b.length) and a.zip(b).all?{|ia,ib| equivalent(ia,ib) }
|
83
|
+
when Hash
|
84
|
+
key_map = guess_mapping(a.keys,b.keys)
|
85
|
+
a.keys.length == b.keys.length and a.keys.all? {|a_k|
|
86
|
+
b_k = key_map[a_k]
|
87
|
+
equivalent(a_k,b_k) and equivalent(a[a_k],b[b_k])
|
88
|
+
}
|
89
|
+
when Exception
|
90
|
+
equivalent(a.message,b.message)
|
91
|
+
when Time,Date,Numeric,nil,true,false,Range,Symbol,String,Regexp
|
92
|
+
a == b
|
93
|
+
else
|
94
|
+
a.to_yaml_properties.all?{|p| equivalent(a.instance_variable_get(p),b.instance_variable_get(p)) }
|
95
|
+
end or note_failure("Expected:\n #{b.inspect}\n but got:\n #{a.inspect}\n")
|
96
|
+
@what_we_are_looking_at.pop
|
97
|
+
result
|
98
|
+
end
|
99
|
+
def equivalent(a,b)
|
100
|
+
if seen_either_before(a,b) then matched_before(a,b) else
|
101
|
+
(same_object(a,b) or (same_class(a,b) and same_properties(a,b))) ; end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
def stripped(x)
|
105
|
+
x.gsub(/ +$/,'').chomp.chomp.gsub(/\n+/,"\n")
|
106
|
+
end
|
107
|
+
def dump_test(obj)
|
108
|
+
z_load = YAML.load(z_dump = ZAML.dump(obj)) rescue "ZAML produced something YAML can't load."
|
109
|
+
y_load = YAML.load(y_dump = YAML.dump(obj)) rescue "YAML failed to eat it's own dogfood"
|
110
|
+
context = {}
|
111
|
+
if ENCODING_KLUDGE && (RUBY_VERSION >= "1.9")
|
112
|
+
if obj.respond_to?(:encoding) && z_load.respond_to?(:force_encoding) then z_load.force_encoding(obj.encoding) ; end
|
113
|
+
end
|
114
|
+
test = Equivalency.test(z_load,obj)
|
115
|
+
assert_block("Reload discrepancy:\n#{test.message}\nZAML:\"\n#{z_dump}\"\nYAML:\"\n#{y_dump}\"\n\n") { test.result }
|
116
|
+
if Equivalency.test(y_load,obj).result and (not obj.is_a? String) and ($skip_text_compare != :skip)
|
117
|
+
assert_equal stripped(y_dump), stripped(z_dump), "Dump discrepancy"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
#
|
122
|
+
# dump tests
|
123
|
+
#
|
124
|
+
|
125
|
+
def test_dump_object
|
126
|
+
dump_test(Object.new)
|
127
|
+
dump_test(My_class.new)
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_dump_nil
|
131
|
+
dump_test(nil)
|
132
|
+
end
|
133
|
+
def test_dump_symbol
|
134
|
+
dump_test(:sym)
|
135
|
+
end
|
136
|
+
def test_dump_true
|
137
|
+
dump_test(true)
|
138
|
+
end
|
139
|
+
def test_dump_false
|
140
|
+
dump_test(false)
|
141
|
+
end
|
142
|
+
def test_dump_numeric
|
143
|
+
dump_test(1)
|
144
|
+
dump_test(1.1)
|
145
|
+
end
|
146
|
+
def test_dump_exception
|
147
|
+
dump_test(Exception.new('error message'))
|
148
|
+
dump_test(ArgumentError.new('error message'))
|
149
|
+
end
|
150
|
+
def test_dump_regexp
|
151
|
+
dump_test(/abc/)
|
152
|
+
dump_test(/a.*(b+)/im)
|
153
|
+
end
|
154
|
+
def test_dump_time
|
155
|
+
dump_test(Time.now)
|
156
|
+
end
|
157
|
+
def test_dump_date
|
158
|
+
dump_test(Date.strptime('2008-08-08'))
|
159
|
+
end
|
160
|
+
def test_dump_range
|
161
|
+
dump_test(1..10)
|
162
|
+
dump_test('a'...'b')
|
163
|
+
end
|
164
|
+
|
165
|
+
def test_dump_short_strings
|
166
|
+
#
|
167
|
+
every_character = (0..255).collect{|n| n.chr }
|
168
|
+
letters = 'a'..'z'
|
169
|
+
some_characters = (0..127).collect{|n| n.chr } - ('A'..'Z').to_a - ('b'..'z').to_a - ('1'..'9').to_a
|
170
|
+
fewer_characters = some_characters - every_character[1..31] + ["\n","\r","\t","\e"] - [127.chr,128.chr]
|
171
|
+
#
|
172
|
+
every_character.each{|c1| dump_test c1 }
|
173
|
+
every_character.each{|c1| dump_test "> "+c1 }
|
174
|
+
every_character.each_with_index{|c1,idx|
|
175
|
+
every_character.each{|c2| dump_test c1+c2 }
|
176
|
+
if idx % 16 == 0 then print ',' ; $stdout.flush ; end
|
177
|
+
} if SLOWNESS >= 1
|
178
|
+
|
179
|
+
letters.each{|c1|
|
180
|
+
letters.each{|c2|
|
181
|
+
print c1,c2,' ',8.chr*3
|
182
|
+
STDOUT.flush
|
183
|
+
letters.each{|c3|
|
184
|
+
dump_test c1+c2+c3
|
185
|
+
letters.each{|c4| dump_test c1+c2+c3+c4 }
|
186
|
+
}
|
187
|
+
}
|
188
|
+
GC.start
|
189
|
+
} if SLOWNESS >= 2 #slow
|
190
|
+
some_characters.each{|c1|
|
191
|
+
some_characters.each{|c2|
|
192
|
+
print((c1+c2).inspect,' ',8.chr*((c1+c2).inspect.length+8))
|
193
|
+
STDOUT.flush
|
194
|
+
some_characters.each{|c3|
|
195
|
+
some_characters.each{|c4| dump_test c1+c2+c3+c4 }
|
196
|
+
}
|
197
|
+
GC.start
|
198
|
+
}
|
199
|
+
} if SLOWNESS >= 3 #slower
|
200
|
+
fewer_characters.each{|c1|
|
201
|
+
fewer_characters.each{|c2|
|
202
|
+
print((c1+c2).inspect,' ',8.chr*((c1+c2).inspect.length+8))
|
203
|
+
STDOUT.flush
|
204
|
+
fewer_characters.each{|c3|
|
205
|
+
fewer_characters.each{|c4|
|
206
|
+
fewer_characters.each{|c5| dump_test c1+c2+c3+c4+c5 }
|
207
|
+
}
|
208
|
+
GC.start
|
209
|
+
}
|
210
|
+
}
|
211
|
+
} if SLOWNESS >= 4 #very slow
|
212
|
+
end
|
213
|
+
|
214
|
+
def test_system_dict_words
|
215
|
+
number_of_dict_words_to_test = 10**( SLOWNESS + 2 )
|
216
|
+
File.readlines(DICT_WORDS_PATH).take(number_of_dict_words_to_test).each{|w| dump_test w.chomp } if File.exists?(DICT_WORDS_PATH)
|
217
|
+
end
|
218
|
+
|
219
|
+
def test_dump_tricky_strings
|
220
|
+
dump_test("")
|
221
|
+
dump_test("#")
|
222
|
+
dump_test("!")
|
223
|
+
dump_test("~")
|
224
|
+
dump_test("=")
|
225
|
+
dump_test("\n")
|
226
|
+
dump_test("\n0")
|
227
|
+
dump_test("\n!")
|
228
|
+
dump_test("##")
|
229
|
+
dump_test("###")
|
230
|
+
dump_test("2:7")
|
231
|
+
dump_test("1:1 x")
|
232
|
+
dump_test(">")
|
233
|
+
dump_test(">>")
|
234
|
+
dump_test("> >")
|
235
|
+
dump_test("> !")
|
236
|
+
dump_test(">++ !")
|
237
|
+
dump_test(">0+ !")
|
238
|
+
dump_test("| |")
|
239
|
+
dump_test("0:0")
|
240
|
+
dump_test("1:2:3")
|
241
|
+
dump_test("+1:2:3")
|
242
|
+
dump_test("1:-2:+3")
|
243
|
+
dump_test("%.:.")
|
244
|
+
dump_test("%.:/")
|
245
|
+
dump_test("!\n")
|
246
|
+
dump_test("!\n\n")
|
247
|
+
dump_test("!\n\n\n\n ")
|
248
|
+
dump_test("!\n\n\n\n \n")
|
249
|
+
dump_test("!\n\n\n\n \n\n\n")
|
250
|
+
dump_test("!\n\n\n\n \n\n\r")
|
251
|
+
dump_test("!\n\n\n\n \n\n ")
|
252
|
+
dump_test("\n")
|
253
|
+
dump_test("\n\n")
|
254
|
+
dump_test("\n\n\n")
|
255
|
+
dump_test("\n\n\n\n ")
|
256
|
+
dump_test("\n\n\n\n \n")
|
257
|
+
dump_test(" ")
|
258
|
+
dump_test(" \r")
|
259
|
+
dump_test("\n\n\n\n \n\n\r")
|
260
|
+
dump_test("\n\n\n\n \n\n ")
|
261
|
+
end
|
262
|
+
|
263
|
+
def test_dump_string
|
264
|
+
dump_test('str')
|
265
|
+
dump_test(" leading and trailing whitespace ")
|
266
|
+
dump_test("a string \n with newline")
|
267
|
+
dump_test("a string with 'quotes'")
|
268
|
+
dump_test("a string with \"double quotes\"")
|
269
|
+
dump_test("a string with \\ escape")
|
270
|
+
dump_test("a really long string" * 10)
|
271
|
+
dump_test("a really long string \n with newline" * 10)
|
272
|
+
dump_test("a really long string with 'quotes'" * 10)
|
273
|
+
dump_test("a really long string with \"double quotes\"" * 10)
|
274
|
+
dump_test("a really long string with \\ escape" * 10)
|
275
|
+
dump_test("string with binary data \x00 \x01 \x02")
|
276
|
+
dump_test(" funky\n test\n")
|
277
|
+
dump_test('"')
|
278
|
+
dump_test("'")
|
279
|
+
dump_test('\\')
|
280
|
+
dump_test("k: v")
|
281
|
+
dump_test(":goo")
|
282
|
+
dump_test("? foo")
|
283
|
+
dump_test("{khkjh}")
|
284
|
+
dump_test("[ha]")
|
285
|
+
dump_test("- - (text) - -")
|
286
|
+
dump_test("\n\n \n \n x\n y\n z\n!\n")
|
287
|
+
end
|
288
|
+
|
289
|
+
def test_dump_strings_that_resemble_literals
|
290
|
+
dump_test("true")
|
291
|
+
dump_test("false")
|
292
|
+
dump_test("null")
|
293
|
+
dump_test("yes")
|
294
|
+
dump_test("no")
|
295
|
+
dump_test("on")
|
296
|
+
dump_test("off")
|
297
|
+
dump_test("nil")
|
298
|
+
dump_test("3")
|
299
|
+
dump_test("3.14")
|
300
|
+
dump_test("1e-6")
|
301
|
+
dump_test("0x345")
|
302
|
+
dump_test("-0x345")
|
303
|
+
dump_test("1e5")
|
304
|
+
end
|
305
|
+
|
306
|
+
STR = 'happy_str'
|
307
|
+
|
308
|
+
HASH = {
|
309
|
+
:nil => nil,
|
310
|
+
:sym => :value,
|
311
|
+
:true => true,
|
312
|
+
:false => false,
|
313
|
+
:int => 100,
|
314
|
+
:float => 1.1,
|
315
|
+
:regexp => /abc/,
|
316
|
+
STR => 'value',
|
317
|
+
:range => 1..10
|
318
|
+
}
|
319
|
+
ARRAY = [ nil, :sym, true, false, 100, 1.1, /abc/, STR, 1..10 ]
|
320
|
+
|
321
|
+
#
|
322
|
+
# hash
|
323
|
+
#
|
324
|
+
|
325
|
+
def test_dump_simple_hash
|
326
|
+
dump_test({:key => 'value'})
|
327
|
+
end
|
328
|
+
def test_dump_hash
|
329
|
+
dump_test(HASH)
|
330
|
+
end
|
331
|
+
def test_dump_simple_nested_hash
|
332
|
+
$skip_text_compare = :skip if INDENTED_ARRAYS_KLUDGE
|
333
|
+
dump_test({:hash => {:key => 'value'}, :array => [1,2,3]})
|
334
|
+
$skip_text_compare = false
|
335
|
+
end
|
336
|
+
def test_dump_nested_hash
|
337
|
+
$skip_text_compare = :skip if INDENTED_ARRAYS_KLUDGE
|
338
|
+
dump_test(HASH.merge(:hash => {:hash => {:key => 'value'}}, :array => [[1,2,3]]))
|
339
|
+
$skip_text_compare = false
|
340
|
+
end
|
341
|
+
|
342
|
+
# def test_dump_self_referential_hash
|
343
|
+
# array = ARRAY + [ARRAY]
|
344
|
+
# dump_test(HASH.merge(:hash => HASH, :array => array))
|
345
|
+
# end
|
346
|
+
|
347
|
+
def test_dump_self_referential_hash
|
348
|
+
if YAML_DUPS_STRINGS_KLUDGE
|
349
|
+
array = ARRAY.dup ; hsh = HASH.dup
|
350
|
+
array.delete(STR) ; hsh.delete(STR)
|
351
|
+
dump_test(hsh.merge(:hash => hsh, :array => (array + [ array ])))
|
352
|
+
else
|
353
|
+
array = ARRAY + [ARRAY]
|
354
|
+
dump_test(HASH.merge(:hash => HASH, :array => array))
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
def test_dump_singlular_self_referential_hash
|
359
|
+
hash = {}
|
360
|
+
hash[hash] = hash
|
361
|
+
dump_test(hash)
|
362
|
+
end
|
363
|
+
def test_dump_hash_value_with_colon
|
364
|
+
hash = { 'a' => 'a value:', 'b' => 'b value' }
|
365
|
+
dump_test(hash)
|
366
|
+
end
|
367
|
+
|
368
|
+
#
|
369
|
+
# array
|
370
|
+
#
|
371
|
+
|
372
|
+
def test_dump_simple_array
|
373
|
+
dump_test([1,2,3])
|
374
|
+
end
|
375
|
+
def test_dump_array
|
376
|
+
dump_test(ARRAY)
|
377
|
+
end
|
378
|
+
def test_dump_simple_nested_array
|
379
|
+
dump_test([{:key => 'value'}, [1,2,3]])
|
380
|
+
end
|
381
|
+
def test_dump_nested_array
|
382
|
+
$skip_text_compare = :skip if INDENTED_ARRAYS_KLUDGE
|
383
|
+
dump_test(ARRAY.concat([{:array => [1,2,3]}, [[1,2,3]]]))
|
384
|
+
$skil_text_compare = false
|
385
|
+
end
|
386
|
+
|
387
|
+
def test_dump_self_referential_array
|
388
|
+
if YAML_DUPS_STRINGS_KLUDGE
|
389
|
+
arr = ARRAY.dup ; hsh = HASH.dup
|
390
|
+
arr.delete(STR) ; hsh.delete(STR)
|
391
|
+
array = arr + [arr, hsh.merge(:hash => hsh)]
|
392
|
+
dump_test(array)
|
393
|
+
else
|
394
|
+
array = ARRAY + [ARRAY, HASH.merge(:hash => HASH)]
|
395
|
+
dump_test(array)
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
def test_dump_singlular_self_referential_array
|
400
|
+
array = []
|
401
|
+
array << array
|
402
|
+
dump_test(array)
|
403
|
+
end
|
404
|
+
|
405
|
+
#
|
406
|
+
# dump various data tests
|
407
|
+
#
|
408
|
+
|
409
|
+
my_range = 7..13
|
410
|
+
my_obj = My_class.new
|
411
|
+
my_dull_object = Object.new
|
412
|
+
my_bob = 'bob'
|
413
|
+
my_exception = Exception.new("Error message")
|
414
|
+
my_runtime_error = RuntimeError.new("This is a runtime error exception")
|
415
|
+
wright_joke = %q{
|
416
|
+
|
417
|
+
I was in the grocery store. I saw a sign that said "pet supplies".
|
418
|
+
|
419
|
+
So I did.
|
420
|
+
|
421
|
+
Then I went outside and saw a sign that said "compact cars".
|
422
|
+
|
423
|
+
-- Steven Wright
|
424
|
+
}
|
425
|
+
a_box_of_cheese = [:cheese]
|
426
|
+
DATA = [1, my_range, my_obj, my_bob, my_dull_object, 2, 'test', " funky\n test\n", true, false,
|
427
|
+
{my_obj => 'obj is the key!'},
|
428
|
+
{:bob => 6.8, :sam => 9.7, :subhash => {:sh1 => 'one', :sh2 => 'two'}},
|
429
|
+
6, my_bob, my_obj, my_range, 'bob', 1..10, 0...8]
|
430
|
+
MORE_DATA = [{
|
431
|
+
:a_regexp => /a.*(b+)/im,
|
432
|
+
:an_exception => my_exception,
|
433
|
+
:a_runtime_error => my_runtime_error,
|
434
|
+
:a_long_string => wright_joke}
|
435
|
+
]
|
436
|
+
NESTED_ARRAYS = [
|
437
|
+
[:one, 'One'],
|
438
|
+
[:two, 'Two'],
|
439
|
+
a_box_of_cheese,
|
440
|
+
[:three, 'Three'],
|
441
|
+
[:four, 'Four'],
|
442
|
+
a_box_of_cheese,
|
443
|
+
[:five, 'Five'],
|
444
|
+
[:six, 'Six']
|
445
|
+
]
|
446
|
+
COMPLEX_DATA = {
|
447
|
+
:data => DATA,
|
448
|
+
:more_data => MORE_DATA,
|
449
|
+
:nested_arrays => NESTED_ARRAYS
|
450
|
+
}
|
451
|
+
|
452
|
+
def test_dump_DATA
|
453
|
+
dump_test(DATA)
|
454
|
+
end
|
455
|
+
def test_dump_MORE_DATA
|
456
|
+
dump_test(MORE_DATA)
|
457
|
+
end
|
458
|
+
def test_dump_NESTED_ARRAYS
|
459
|
+
dump_test(NESTED_ARRAYS)
|
460
|
+
end
|
461
|
+
def test_dump_COMPLEX_DATA
|
462
|
+
dump_test(COMPLEX_DATA)
|
463
|
+
end
|
464
|
+
def test_indentation_array_edge_cases
|
465
|
+
dump_test({[]=>[]})
|
466
|
+
dump_test([[]])
|
467
|
+
dump_test([[[],[]]])
|
468
|
+
end
|
469
|
+
def test_string_identity
|
470
|
+
a = 'str'
|
471
|
+
dump_test([a,a])
|
472
|
+
end
|
473
|
+
end
|