sj-plist 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/MIT-LICENSE +21 -0
- data/README +40 -0
- data/Rakefile +135 -0
- data/docs/USAGE +104 -0
- data/lib/plist.rb +22 -0
- data/lib/plist/ascii.rb +251 -0
- data/lib/plist/binary.rb +510 -0
- data/lib/plist/generator.rb +240 -0
- data/lib/plist/parser.rb +224 -0
- data/test/assets/AlbumData.xml +203 -0
- data/test/assets/Cookies.plist +104 -0
- data/test/assets/commented.plist +9 -0
- data/test/assets/example_data.bin +0 -0
- data/test/assets/example_data.jpg +0 -0
- data/test/assets/example_data.plist +259 -0
- data/test/assets/example_data_ascii.plist +51 -0
- data/test/assets/ruby.plist +1696 -0
- data/test/assets/test_data_elements.plist +24 -0
- data/test/assets/test_empty_key.plist +13 -0
- data/test/test_ascii.rb +143 -0
- data/test/test_binary.rb +116 -0
- data/test/test_data_elements.rb +115 -0
- data/test/test_generator.rb +59 -0
- data/test/test_generator_basic_types.rb +58 -0
- data/test/test_generator_collections.rb +82 -0
- data/test/test_parser.rb +100 -0
- metadata +80 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>stringio</key>
|
|
6
|
+
<data>dGhpcyBpcyBhIHN0cmluZ2lvIG9iamVjdA==
|
|
7
|
+
</data>
|
|
8
|
+
<key>file</key>
|
|
9
|
+
<data>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
10
|
+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
11
|
+
AAAAAAAAAAAAAA==
|
|
12
|
+
</data>
|
|
13
|
+
<key>io</key>
|
|
14
|
+
<data>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
15
|
+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
16
|
+
AAAAAAAAAAAAAA==
|
|
17
|
+
</data>
|
|
18
|
+
<key>marshal</key>
|
|
19
|
+
<!-- The <data> element below contains a Ruby object which has been serialized with Marshal.dump. -->
|
|
20
|
+
<data>BAhvOhZNYXJzaGFsYWJsZU9iamVjdAY6CUBmb28iHnRoaXMgb2JqZWN0IHdh
|
|
21
|
+
cyBtYXJzaGFsZWQ=
|
|
22
|
+
</data>
|
|
23
|
+
</dict>
|
|
24
|
+
</plist>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>key</key>
|
|
6
|
+
<dict>
|
|
7
|
+
<key></key>
|
|
8
|
+
<string>1</string>
|
|
9
|
+
<key>subkey</key>
|
|
10
|
+
<string>2</string>
|
|
11
|
+
</dict>
|
|
12
|
+
</dict>
|
|
13
|
+
</plist>
|
data/test/test_ascii.rb
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require "test/unit"
|
|
4
|
+
require "date"
|
|
5
|
+
require "plist/ascii"
|
|
6
|
+
|
|
7
|
+
class TestAscii < Test::Unit::TestCase
|
|
8
|
+
def test_should_parse_a_simple_dictionary
|
|
9
|
+
assert_equal({'a' => 'b'}, parse("{ a = b; }"))
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def test_should_parse_a_simple_array
|
|
13
|
+
assert_equal(%w[1 2 3], parse("(1, 2, 3)"))
|
|
14
|
+
assert_equal(%w[foo], parse("(foo, )"))
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def test_should_assume_dictionary_keys_are_strings_when_they_start_with_a_number
|
|
18
|
+
assert_equal({ '1' => 'foo' }, parse("{ 1 = foo; }"))
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def test_should_correctly_parse_escaped_unicode_points
|
|
22
|
+
assert_equal({'foo' => "æ"}, parse('{ foo = "\u00e6"; }'))
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def test_should_always_return_string_keys
|
|
26
|
+
assert_equal({'1234' => 'boo'}, parse_with_numbers('{ 1234 = boo; }'))
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def test_should_correctly_parse_control_chars
|
|
30
|
+
assert_equal({'foo' => "\a\v\r\t\n\b\f"}, parse('{ foo = "\a\v\r\t\n\b\f"; }'))
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def test_should_correctly_parse_octal_escapes
|
|
34
|
+
expected = "\303\246"
|
|
35
|
+
expected.force_encoding("BINARY") if expected.respond_to?(:force_encoding)
|
|
36
|
+
assert_equal({'foo' => expected}, parse('{ foo = "\303\246"; }'))
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def test_should_correctly_parse_escaped_strings
|
|
40
|
+
assert_equal({'foo' => '"hello world"'}, parse('{ foo = "\"hello world\""; }'))
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def test_should_correctly_parse_NSDate_strings
|
|
44
|
+
assert_equal({'time' => DateTime.parse("2008-11-22 14:17:04 +0100")}, parse('{ time = 2008-11-22 14:17:04 +0100;}'))
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def test_should_parse_floats
|
|
48
|
+
assert_equal({ 'hello' => 1.2 }, parse_with_numbers("{ hello = 1.2; }"))
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def test_should_parse_ints
|
|
52
|
+
assert_equal([1,2,3], parse_with_numbers("(1, 2, 3)"))
|
|
53
|
+
assert_equal({ 'hello' => "12abc" }, parse_with_numbers('{ hello = 12abc; }'))
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def test_should_parse_booleans
|
|
57
|
+
assert_equal({'foo' => true}, parse_with_bools("{foo = true;}"))
|
|
58
|
+
assert_equal({'foo' => "1"}, parse("{foo = true;}"))
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def test_should_parse_data
|
|
62
|
+
assert_equal({'data' => "foo\n"}, parse("{data = <666f6f0a>;}"))
|
|
63
|
+
assert_equal(asset("example_data.jpg"), parse(asset("example_data_ascii.plist"))['image'])
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
#
|
|
67
|
+
# errors
|
|
68
|
+
#
|
|
69
|
+
|
|
70
|
+
def test_should_raise_error_if_given_a_non_string_key
|
|
71
|
+
assert_raises Plist::AsciiParser::ParseError do
|
|
72
|
+
parse_with_numbers "{ 1.2 = foo; }"
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def test_should_raise_error_on_missing_semicolons
|
|
77
|
+
assert_raises Plist::AsciiParser::ParseError do
|
|
78
|
+
parse "{ foo = bar }"
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def test_should_raise_error_on_missing_closing_parenthesis
|
|
83
|
+
assert_raises Plist::AsciiParser::ParseError do
|
|
84
|
+
parse "( foo, bar "
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def test_should_raise_error_on_missing_end_quote
|
|
89
|
+
assert_raises Plist::AsciiParser::ParseError do
|
|
90
|
+
parse '{ foo = "bar; }'
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def test_wshould_raise_error_on_empty_string
|
|
95
|
+
assert_raises Plist::AsciiParser::ParseError do
|
|
96
|
+
parse ''
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
#
|
|
101
|
+
# other
|
|
102
|
+
#
|
|
103
|
+
|
|
104
|
+
def test_should_parse_textmate_ruby_grammar_without_errors
|
|
105
|
+
assert_nothing_raised do
|
|
106
|
+
parse asset("ruby.plist")
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def test_should_handle_a_stringio_as_input
|
|
111
|
+
io = StringIO.new("(a,b,c)")
|
|
112
|
+
assert_equal(%w[a b c], parse(io))
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def test_should_handle_an_io_as_input
|
|
116
|
+
File.open(path = "test.txt", "w") { |file| file << "{baz=(1,2,3);}" }
|
|
117
|
+
io = File.open(path, "r")
|
|
118
|
+
assert_equal({'baz' => [1,2,3] }, parse_with_numbers(io))
|
|
119
|
+
ensure
|
|
120
|
+
io.close
|
|
121
|
+
File.delete(io.path)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
#
|
|
125
|
+
# helpers
|
|
126
|
+
#
|
|
127
|
+
|
|
128
|
+
def parse(str)
|
|
129
|
+
Plist.parse_ascii(str)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def parse_with_numbers(str)
|
|
133
|
+
Plist.parse_ascii(str, :parse_numbers => true)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def parse_with_bools(str)
|
|
137
|
+
Plist.parse_ascii(str, :parse_booleans => true)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def asset(filename)
|
|
141
|
+
File.read("#{File.dirname(__FILE__)}/assets/#{filename}")
|
|
142
|
+
end
|
|
143
|
+
end
|
data/test/test_binary.rb
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# encoding: binary
|
|
2
|
+
require "test/unit"
|
|
3
|
+
require "plist"
|
|
4
|
+
|
|
5
|
+
class TestBinary < Test::Unit::TestCase
|
|
6
|
+
def test_binary_min_byte_size
|
|
7
|
+
# 1-, 2-, and 4-byte integers are unsigned.
|
|
8
|
+
assert_equal(1, Plist::Binary.send(:min_byte_size, 0))
|
|
9
|
+
assert_equal(1, Plist::Binary.send(:min_byte_size, 0xff))
|
|
10
|
+
assert_equal(2, Plist::Binary.send(:min_byte_size, 0x100))
|
|
11
|
+
assert_equal(2, Plist::Binary.send(:min_byte_size, 0xffff))
|
|
12
|
+
assert_equal(4, Plist::Binary.send(:min_byte_size, 0x10000))
|
|
13
|
+
assert_equal(4, Plist::Binary.send(:min_byte_size, 0xffffffff))
|
|
14
|
+
# 8- and 16-byte integers are signed.
|
|
15
|
+
assert_equal(8, Plist::Binary.send(:min_byte_size, 0x100000000))
|
|
16
|
+
assert_equal(8, Plist::Binary.send(:min_byte_size, 0x7fffffffffffffff))
|
|
17
|
+
assert_equal(16, Plist::Binary.send(:min_byte_size, 0x8000000000000000))
|
|
18
|
+
assert_equal(16, Plist::Binary.send(:min_byte_size, 0x7fffffffffffffffffffffffffffffff))
|
|
19
|
+
assert_raises(RangeError) { Plist::Binary.send(:min_byte_size, 0x80000000000000000000000000000000) }
|
|
20
|
+
assert_equal(8, Plist::Binary.send(:min_byte_size, -1))
|
|
21
|
+
assert_equal(8, Plist::Binary.send(:min_byte_size, -0x8000000000000000))
|
|
22
|
+
assert_equal(16, Plist::Binary.send(:min_byte_size, -0x8000000000000001))
|
|
23
|
+
assert_equal(16, Plist::Binary.send(:min_byte_size, -0x80000000000000000000000000000000))
|
|
24
|
+
assert_raises(RangeError) { Plist::Binary.send(:min_byte_size, -0x80000000000000000000000000000001) }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def test_binary_pack_int
|
|
28
|
+
assert_equal("\x0", Plist::Binary.send(:pack_int, 0, 1))
|
|
29
|
+
assert_equal("\x0\x34", Plist::Binary.send(:pack_int, 0x34, 2))
|
|
30
|
+
assert_equal("\x0\xde\xdb\xef", Plist::Binary.send(:pack_int, 0xdedbef, 4))
|
|
31
|
+
assert_equal("\x0\xca\xfe\x0\x0\xde\xdb\xef", Plist::Binary.send(:pack_int, 0xcafe0000dedbef, 8))
|
|
32
|
+
assert_equal("\x0\x7f\xf7\x0\x0\x12\x34\x0\x0\xca\xfe\x0\x0\xde\xdb\xef", Plist::Binary.send(:pack_int, 0x7ff7000012340000cafe0000dedbef, 16))
|
|
33
|
+
assert_raises(ArgumentError) { Plist::Binary.send(:pack_int, -1, 1) }
|
|
34
|
+
assert_raises(ArgumentError) { Plist::Binary.send(:pack_int, -1, 2) }
|
|
35
|
+
assert_raises(ArgumentError) { Plist::Binary.send(:pack_int, -1, 4) }
|
|
36
|
+
assert_equal("\xff\xff\xff\xff\xff\xff\xff\xff", Plist::Binary.send(:pack_int, -1, 8))
|
|
37
|
+
assert_equal("\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", Plist::Binary.send(:pack_int, -1, 16))
|
|
38
|
+
[-2,0,3,5,6,7,9,10,11,12,13,14,15,17,18,19,20,32].each do |i|
|
|
39
|
+
assert_raises(ArgumentError) { Plist::Binary.send(:pack_int, 0, i) }
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def test_binary_plist_data
|
|
44
|
+
assert_equal("\x4ahelloworld",
|
|
45
|
+
Plist::Binary.send(:binary_plist_data, "helloworld"))
|
|
46
|
+
data = "x" * 32000
|
|
47
|
+
assert_equal("\x4f\x11\x7d\x00#{data}",
|
|
48
|
+
Plist::Binary.send(:binary_plist_data, data))
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def test_flatten_collection
|
|
52
|
+
assert_equal([[1, 2, 3], :a, :b, :c],
|
|
53
|
+
Plist::Binary.send(:flatten_collection, [:a, :b, :c]))
|
|
54
|
+
assert_equal([[1, 2, 3, 4], :a, :b, :c, [1, 1]],
|
|
55
|
+
Plist::Binary.send(:flatten_collection, [:a, :b, :c, [:a, :a]]))
|
|
56
|
+
assert_equal(["booger"],
|
|
57
|
+
Plist::Binary.send(:flatten_collection, "booger"))
|
|
58
|
+
assert_equal([[1, 2], "hello", { 3 => 4 }, "key", [5, 6, 7], 1, 2, 3],
|
|
59
|
+
Plist::Binary.send(:flatten_collection, ["hello", { :key => [1, 2, 3] }]))
|
|
60
|
+
ary = [:a, :b, :c]
|
|
61
|
+
assert_equal([[1, 5], [2, 3, 4], :a, :b, :c, { 1 => 6 }, "whee"],
|
|
62
|
+
Plist::Binary.send(:flatten_collection, [ary, { ary => "whee" }]))
|
|
63
|
+
hsh = { :a => :b }
|
|
64
|
+
assert_equal([[1, 4], { 2 => 3 }, "a", :b, [5, 6, 1], 1, 2],
|
|
65
|
+
Plist::Binary.send(:flatten_collection, [hsh, [1, 2, hsh]]))
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def test_binary_plist_obj
|
|
69
|
+
assert_equal("\x5bHello World",
|
|
70
|
+
Plist::Binary.send(:binary_plist_obj, "Hello World"))
|
|
71
|
+
assert_equal("\x5f\x10\x1bDomo-kun's Angry Smash Fest",
|
|
72
|
+
Plist::Binary.send(:binary_plist_obj, "Domo-kun's Angry Smash Fest"))
|
|
73
|
+
assert_equal("\x63\x59\x7d\x30\x4d\x30\x60",
|
|
74
|
+
Plist::Binary.send(:binary_plist_obj, "好きだ"))
|
|
75
|
+
assert_raises(ArgumentError) { Plist::Binary.send(:binary_plist_obj, "𝄢") }
|
|
76
|
+
assert_equal("\x63\x59\x7d\x30\x4d\x30\x60",
|
|
77
|
+
Plist::Binary.send(:binary_plist_obj, "好きだ"))
|
|
78
|
+
assert_equal("\x66\000s\000e\0\361\000o\000r\000a",
|
|
79
|
+
Plist::Binary.send(:binary_plist_obj, "señora"))
|
|
80
|
+
assert_equal("\x23#{[3.14159].pack('G')}",
|
|
81
|
+
Plist::Binary.send(:binary_plist_obj, 3.14159))
|
|
82
|
+
assert_equal("\x9", Plist::Binary.send(:binary_plist_obj, true))
|
|
83
|
+
assert_equal("\x8", Plist::Binary.send(:binary_plist_obj, false))
|
|
84
|
+
assert_equal("\x33\xc1\xcd\x27\xe4\x2\x80\x0\x0",
|
|
85
|
+
Plist::Binary.send(:binary_plist_obj, Time.at(123)))
|
|
86
|
+
sio = StringIO.new("Hello World")
|
|
87
|
+
assert_equal("\x4bHello World", Plist::Binary.send(:binary_plist_obj, sio))
|
|
88
|
+
assert_equal("\xa3\x1\x2\x3",
|
|
89
|
+
Plist::Binary.send(:binary_plist_obj, [1, 2, 3], 1))
|
|
90
|
+
assert_equal("\xaf\x10\x10\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10",
|
|
91
|
+
Plist::Binary.send(:binary_plist_obj, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], 1))
|
|
92
|
+
assert_equal("\xa3\x0\x1\x0\x2\x0\x3",
|
|
93
|
+
Plist::Binary.send(:binary_plist_obj, [1, 2, 3], 2))
|
|
94
|
+
assert_equal("\xd2\x1\x3\x2\x4",
|
|
95
|
+
Plist::Binary.send(:binary_plist_obj, {1=>2, 3=>4}, 1))
|
|
96
|
+
assert_equal("\xdf\x10\x10\x5\x0\xb\x6\x1\xc\x7\x2\xd\x8\x3\xe\x9\x4\xf\xa\x15\x10\x1b\x16\x11\x1c\x17\x12\x1d\x18\x13\x1e\x19\x14\x1f\x1a",
|
|
97
|
+
Plist::Binary.send(:binary_plist_obj, {5=>21, 11=>27, 0=>16, 6=>22, 12=>28, 1=>17, 7=>23, 13=>29, 2=>18, 8=>24, 14=>30, 3=>19, 9=>25, 15=>31, 4=>20, 10=>26}, 1))
|
|
98
|
+
assert_equal("\xd2\x0\x1\x0\x3\x0\x2\x0\x4",
|
|
99
|
+
Plist::Binary.send(:binary_plist_obj, {1=>2, 3=>4}, 2))
|
|
100
|
+
assert_equal("\xc3\x1\x2\x3",
|
|
101
|
+
Plist::Binary.send(:binary_plist_obj, Set.new([1, 2, 3]), 1))
|
|
102
|
+
assert_equal("\xcf\x10\x10\x10\x5\xb\x6\xc\x1\x7\xd\x2\x8\xe\x3\x9\xf\x4\xa",
|
|
103
|
+
Plist::Binary.send(:binary_plist_obj, Set.new([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]), 1))
|
|
104
|
+
assert_equal("\xc3\x0\x1\x0\x2\x0\x3",
|
|
105
|
+
Plist::Binary.send(:binary_plist_obj, Set.new([1, 2, 3]), 2))
|
|
106
|
+
assert_equal("\x49\x4\x8/\x9narf\0",
|
|
107
|
+
Plist::Binary.send(:binary_plist_obj, /narf/))
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def test_binary_plist
|
|
111
|
+
assert_equal("bplist00\x55hello\x8\x0\x0\x0\x0\x0\x0\x1\x1\x0\x0\x0\x0\x0\x0\x0\x1\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\xe",
|
|
112
|
+
Plist::Binary.binary_plist("hello"))
|
|
113
|
+
assert_equal("bplist00\xa4\x1\x2\x3\x6\x45\x4\x8\x3a\x6\x61\x45\x4\x8\x3a\x6\x62\xd1\x4\x5\x55\x73\x74\x75\x66\x66\x58\x77\x68\x61\x74\x65\x76\x65\x72\x10\x7b\x8\xd\x13\x19\x1c\x22\x2b\x0\x0\x0\x0\x0\x0\x1\x1\x0\x0\x0\x0\x0\x0\x0\x7\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x2d",
|
|
114
|
+
Plist::Binary.binary_plist([:a, :b, { :stuff => "whatever" }, 123]))
|
|
115
|
+
end
|
|
116
|
+
end
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
##############################################################
|
|
2
|
+
# Copyright 2006, Ben Bleything <ben@bleything.net> and #
|
|
3
|
+
# Patrick May <patrick@hexane.org> #
|
|
4
|
+
# #
|
|
5
|
+
# Distributed under the MIT license. #
|
|
6
|
+
##############################################################
|
|
7
|
+
|
|
8
|
+
require 'test/unit'
|
|
9
|
+
require 'plist'
|
|
10
|
+
require 'stringio'
|
|
11
|
+
|
|
12
|
+
class MarshalableObject
|
|
13
|
+
attr_accessor :foo
|
|
14
|
+
|
|
15
|
+
def initialize(str)
|
|
16
|
+
@foo = str
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class TestDataElements < Test::Unit::TestCase
|
|
21
|
+
@@result = Plist::parse_xml('test/assets/test_data_elements.plist')
|
|
22
|
+
|
|
23
|
+
def test_marshal
|
|
24
|
+
expected = <<END
|
|
25
|
+
<!-- The <data> element below contains a Ruby object which has been serialized with Marshal.dump. -->
|
|
26
|
+
<data>
|
|
27
|
+
BAhvOhZNYXJzaGFsYWJsZU9iamVjdAY6CUBmb28iHnRoaXMgb2JqZWN0IHdhcyBtYXJz
|
|
28
|
+
aGFsZWQ=
|
|
29
|
+
</data>
|
|
30
|
+
END
|
|
31
|
+
|
|
32
|
+
mo = MarshalableObject.new('this object was marshaled')
|
|
33
|
+
|
|
34
|
+
assert_equal expected.chomp, Plist::Emit.dump(mo, false).chomp
|
|
35
|
+
|
|
36
|
+
assert_instance_of MarshalableObject, @@result['marshal']
|
|
37
|
+
|
|
38
|
+
assert_equal mo.foo, @@result['marshal'].foo
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def test_generator_io_and_file
|
|
42
|
+
expected = <<END
|
|
43
|
+
<data>
|
|
44
|
+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
45
|
+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
|
|
46
|
+
</data>
|
|
47
|
+
END
|
|
48
|
+
|
|
49
|
+
expected.chomp!
|
|
50
|
+
|
|
51
|
+
fd = IO.sysopen('test/assets/example_data.bin')
|
|
52
|
+
io = IO.open(fd, 'r')
|
|
53
|
+
|
|
54
|
+
# File is a subclass of IO, so catching IO in the dispatcher should work for File as well...
|
|
55
|
+
f = File.open('test/assets/example_data.bin')
|
|
56
|
+
|
|
57
|
+
assert_equal expected, Plist::Emit.dump(io, false).chomp
|
|
58
|
+
assert_equal expected, Plist::Emit.dump(f, false).chomp
|
|
59
|
+
|
|
60
|
+
assert_instance_of StringIO, @@result['io']
|
|
61
|
+
assert_instance_of StringIO, @@result['file']
|
|
62
|
+
|
|
63
|
+
io.rewind
|
|
64
|
+
f.rewind
|
|
65
|
+
|
|
66
|
+
assert_equal io.read, @@result['io'].read
|
|
67
|
+
assert_equal f.read, @@result['file'].read
|
|
68
|
+
|
|
69
|
+
io.close
|
|
70
|
+
f.close
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def test_generator_string_io
|
|
74
|
+
expected = <<END
|
|
75
|
+
<data>
|
|
76
|
+
dGhpcyBpcyBhIHN0cmluZ2lvIG9iamVjdA==
|
|
77
|
+
</data>
|
|
78
|
+
END
|
|
79
|
+
|
|
80
|
+
sio = StringIO.new('this is a stringio object')
|
|
81
|
+
|
|
82
|
+
assert_equal expected.chomp, Plist::Emit.dump(sio, false).chomp
|
|
83
|
+
|
|
84
|
+
assert_instance_of StringIO, @@result['stringio']
|
|
85
|
+
|
|
86
|
+
sio.rewind
|
|
87
|
+
assert_equal sio.read, @@result['stringio'].read
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# this functionality is credited to Mat Schaffer,
|
|
91
|
+
# who discovered the plist with the data tag
|
|
92
|
+
# supplied the test data, and provided the parsing code.
|
|
93
|
+
def test_data
|
|
94
|
+
# test reading plist <data> elements
|
|
95
|
+
data = Plist::parse_xml("test/assets/example_data.plist");
|
|
96
|
+
assert_equal( File.open("test/assets/example_data.jpg"){|f| f.read }, data['image'].read )
|
|
97
|
+
|
|
98
|
+
# test writing data elements
|
|
99
|
+
expected = File.read("test/assets/example_data.plist")
|
|
100
|
+
result = data.to_plist
|
|
101
|
+
#File.open('result.plist', 'w') {|f|f.write(result)} # debug
|
|
102
|
+
assert_equal( expected, result )
|
|
103
|
+
|
|
104
|
+
# Test changing the <data> object in the plist to a StringIO and writing.
|
|
105
|
+
# This appears extraneous given that plist currently returns a StringIO,
|
|
106
|
+
# so the above writing test also flexes StringIO#to_plist_node.
|
|
107
|
+
# However, the interface promise is to return an IO, not a particular class.
|
|
108
|
+
# plist used to return Tempfiles, which was changed solely for performance reasons.
|
|
109
|
+
data['image'] = StringIO.new( File.read("test/assets/example_data.jpg"))
|
|
110
|
+
|
|
111
|
+
assert_equal(expected, data.to_plist )
|
|
112
|
+
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
##############################################################
|
|
2
|
+
# Copyright 2006, Ben Bleything <ben@bleything.net> and #
|
|
3
|
+
# Patrick May <patrick@hexane.org> #
|
|
4
|
+
# #
|
|
5
|
+
# Distributed under the MIT license. #
|
|
6
|
+
##############################################################
|
|
7
|
+
|
|
8
|
+
require 'test/unit'
|
|
9
|
+
require 'plist'
|
|
10
|
+
|
|
11
|
+
class SerializableObject
|
|
12
|
+
attr_accessor :foo
|
|
13
|
+
|
|
14
|
+
def initialize(str)
|
|
15
|
+
@foo = str
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def to_plist_node
|
|
19
|
+
return "<string>#{CGI::escapeHTML @foo}</string>"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class TestGenerator < Test::Unit::TestCase
|
|
24
|
+
def test_to_plist_vs_plist_emit_dump_no_envelope
|
|
25
|
+
source = [1, :b, true]
|
|
26
|
+
|
|
27
|
+
to_plist = source.to_plist(false)
|
|
28
|
+
plist_emit_dump = Plist::Emit.dump(source, false)
|
|
29
|
+
|
|
30
|
+
assert_equal to_plist, plist_emit_dump
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def test_to_plist_vs_plist_emit_dump_with_envelope
|
|
34
|
+
source = [1, :b, true]
|
|
35
|
+
|
|
36
|
+
to_plist = source.to_plist
|
|
37
|
+
plist_emit_dump = Plist::Emit.dump(source)
|
|
38
|
+
|
|
39
|
+
assert_equal to_plist, plist_emit_dump
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def test_dumping_serializable_object
|
|
43
|
+
str = 'this object implements #to_plist_node'
|
|
44
|
+
so = SerializableObject.new(str)
|
|
45
|
+
|
|
46
|
+
assert_equal "<string>#{str}</string>", Plist::Emit.dump(so, false)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def test_write_plist
|
|
50
|
+
data = [1, :two, {:c => 'dee'}]
|
|
51
|
+
|
|
52
|
+
data.save_plist('test.plist')
|
|
53
|
+
file = File.open('test.plist') {|f| f.read}
|
|
54
|
+
|
|
55
|
+
assert_equal file, data.to_plist
|
|
56
|
+
|
|
57
|
+
File.unlink('test.plist')
|
|
58
|
+
end
|
|
59
|
+
end
|