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