plist2 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,24 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//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//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>
@@ -0,0 +1,124 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'test/unit'
4
+ require 'plist'
5
+ require 'stringio'
6
+
7
+ class MarshalableObject
8
+ attr_accessor :foo
9
+
10
+ def initialize(str)
11
+ @foo = str
12
+ end
13
+ end
14
+
15
+ class TestDataElements < Test::Unit::TestCase
16
+
17
+ def setup
18
+ @result = Plist.parse_xml( 'test/assets/test_data_elements.plist' )
19
+ end
20
+
21
+ def test_data_object_header
22
+ expected = <<END
23
+ <!-- The <data> element below contains a Ruby object which has been serialized with Marshal.dump. -->
24
+ <data>
25
+ BAhvOhZNYXJzaGFsYWJsZU9iamVjdAY6CUBmb28iHnRoaXMgb2JqZWN0IHdhcyBtYXJz
26
+ aGFsZWQ=
27
+ </data>
28
+ END
29
+ expected_elements = expected.chomp.split( "\n" )
30
+
31
+ actual = Plist::Emit.dump( Object.new, false )
32
+ actual_elements = actual.chomp.split( "\n" )
33
+
34
+ # check for header
35
+ assert_equal expected_elements.shift, actual_elements.shift
36
+
37
+ # check for opening and closing data tags
38
+ assert_equal expected_elements.shift, actual_elements.shift
39
+ assert_equal expected_elements.pop, actual_elements.pop
40
+ end
41
+
42
+ def test_marshal_round_trip
43
+ expected = MarshalableObject.new('this object was marshaled')
44
+ actual = Plist.parse_xml( Plist::Emit.dump(expected, false) )
45
+
46
+ assert_kind_of expected.class, actual
47
+ assert_equal expected.foo, actual.foo
48
+ end
49
+
50
+ def test_generator_io_and_file
51
+ expected = <<END
52
+ <data>
53
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
54
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
55
+ </data>
56
+ END
57
+
58
+ expected.chomp!
59
+
60
+ fd = IO.sysopen('test/assets/example_data.bin')
61
+ io = IO.open(fd, 'r')
62
+
63
+ # File is a subclass of IO, so catching IO in the dispatcher should work for File as well...
64
+ f = File.open('test/assets/example_data.bin')
65
+
66
+ assert_equal expected, Plist::Emit.dump(io, false).chomp
67
+ assert_equal expected, Plist::Emit.dump(f, false).chomp
68
+
69
+ assert_instance_of StringIO, @result['io']
70
+ assert_instance_of StringIO, @result['file']
71
+
72
+ io.rewind
73
+ f.rewind
74
+
75
+ assert_equal io.read, @result['io'].read
76
+ assert_equal f.read, @result['file'].read
77
+
78
+ io.close
79
+ f.close
80
+ end
81
+
82
+ def test_generator_string_io
83
+ expected = <<END
84
+ <data>
85
+ dGhpcyBpcyBhIHN0cmluZ2lvIG9iamVjdA==
86
+ </data>
87
+ END
88
+
89
+ sio = StringIO.new('this is a stringio object')
90
+
91
+ assert_equal expected.chomp, Plist::Emit.dump(sio, false).chomp
92
+
93
+ assert_instance_of StringIO, @result['stringio']
94
+
95
+ sio.rewind
96
+ assert_equal sio.read, @result['stringio'].read
97
+ end
98
+
99
+ # this functionality is credited to Mat Schaffer,
100
+ # who discovered the plist with the data tag
101
+ # supplied the test data, and provided the parsing code.
102
+ def test_data
103
+ # test reading plist <data> elements
104
+ data = Plist::parse_xml("test/assets/example_data.plist");
105
+ assert_equal( File.open("test/assets/example_data.jpg"){|f| f.read }, data['image'].read )
106
+
107
+ # test writing data elements
108
+ expected = File.read("test/assets/example_data.plist")
109
+ result = data.to_plist
110
+ #File.open('result.plist', 'w') {|f|f.write(result)} # debug
111
+ assert_equal( expected, result )
112
+
113
+ # Test changing the <data> object in the plist to a StringIO and writing.
114
+ # This appears extraneous given that plist currently returns a StringIO,
115
+ # so the above writing test also flexes StringIO#to_plist_node.
116
+ # However, the interface promise is to return an IO, not a particular class.
117
+ # plist used to return Tempfiles, which was changed solely for performance reasons.
118
+ data['image'] = StringIO.new( File.read("test/assets/example_data.jpg"))
119
+
120
+ assert_equal(expected, data.to_plist )
121
+
122
+ end
123
+
124
+ end
@@ -0,0 +1,110 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'test/unit'
4
+ require 'plist'
5
+
6
+ class SerializableObject
7
+ attr_accessor :foo
8
+
9
+ def initialize(str)
10
+ @foo = str
11
+ end
12
+
13
+ def to_plist_node
14
+ return "<string>#{CGI::escapeHTML @foo}</string>"
15
+ end
16
+ end
17
+
18
+ class TestGenerator < Test::Unit::TestCase
19
+ def test_to_plist_vs_plist_emit_dump_no_envelope
20
+ source = [1, :b, true]
21
+
22
+ to_plist = source.to_plist(false)
23
+ plist_emit_dump = Plist::Emit.dump(source, false)
24
+
25
+ assert_equal to_plist, plist_emit_dump
26
+ end
27
+
28
+ def test_to_plist_vs_plist_emit_dump_with_envelope
29
+ source = [1, :b, true]
30
+
31
+ to_plist = source.to_plist
32
+ plist_emit_dump = Plist::Emit.dump(source)
33
+
34
+ assert_equal to_plist, plist_emit_dump
35
+ end
36
+
37
+ def test_dumping_serializable_object
38
+ str = 'this object implements #to_plist_node'
39
+ so = SerializableObject.new(str)
40
+
41
+ assert_equal "<string>#{str}</string>", Plist::Emit.dump(so, false)
42
+ end
43
+
44
+ def test_write_plist
45
+ data = [1, :two, {:c => 'dee'}]
46
+
47
+ data.save_plist('test.plist')
48
+ file = File.open('test.plist') {|f| f.read}
49
+
50
+ assert_equal file, data.to_plist
51
+
52
+ File.unlink('test.plist')
53
+ end
54
+
55
+ def spaces_to_tabs(s)
56
+ return s.gsub("\s\s", "\t")
57
+ end
58
+
59
+ # The hash in this test was failing with 'hsh.keys.sort',
60
+ # we are making sure it works with 'hsh.keys.sort_by'.
61
+ def test_sorting_keys
62
+ hsh = {:key1 => 1, :key4 => 4, 'key2' => 2, :key3 => 3}
63
+ expected = <<-STR
64
+ <dict>
65
+ <key>key1</key>
66
+ <integer>1</integer>
67
+ <key>key2</key>
68
+ <integer>2</integer>
69
+ <key>key3</key>
70
+ <integer>3</integer>
71
+ <key>key4</key>
72
+ <integer>4</integer>
73
+ </dict>
74
+ STR
75
+ expected = spaces_to_tabs(expected)
76
+ assert_equal expected, Plist::Emit.dump(hsh, false)
77
+ end
78
+
79
+ def test_hash_is_sorted
80
+ expected = <<END
81
+ <dict>
82
+ <key>a</key>
83
+ <string>a</string>
84
+ <key>b</key>
85
+ <string>b</string>
86
+ </dict>
87
+ END
88
+ h = Hash.new
89
+ h['b'] = 'b'
90
+ h['a'] = 'a'
91
+ expected = spaces_to_tabs(expected)
92
+ assert_equal expected, Plist::Emit.dump(h, false)
93
+ end
94
+
95
+ def test_hash_keeps_order_when_desired
96
+ expected = <<END
97
+ <dict>
98
+ <key>b</key>
99
+ <string>b</string>
100
+ <key>a</key>
101
+ <string>a</string>
102
+ </dict>
103
+ END
104
+ h = Hash.new
105
+ h['b'] = 'b'
106
+ h['a'] = 'a'
107
+ expected = spaces_to_tabs(expected)
108
+ assert_equal expected, Plist::Emit.dump(h, false, :sort => false)
109
+ end
110
+ end
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'test/unit'
4
+ require 'plist'
5
+
6
+ class TestGeneratorBasicTypes < Test::Unit::TestCase
7
+ def wrap(tag, content)
8
+ return "<#{tag}>#{content}</#{tag}>"
9
+ end
10
+
11
+ def test_strings
12
+ expected = wrap('string', 'testdata')
13
+
14
+ assert_equal expected, Plist::Emit.dump('testdata', false).chomp
15
+ assert_equal expected, Plist::Emit.dump(:testdata, false).chomp
16
+ end
17
+
18
+ def test_strings_with_escaping
19
+ expected = wrap('string', "&lt;Fish &amp; Chips&gt;")
20
+
21
+ assert_equal expected, Plist::Emit.dump('<Fish & Chips>', false).chomp
22
+ end
23
+
24
+ def test_integers
25
+ [42, 2376239847623987623, -8192].each do |i|
26
+ assert_equal wrap('integer', i), Plist::Emit.dump(i, false).chomp
27
+ end
28
+ end
29
+
30
+ def test_floats
31
+ [3.14159, -38.3897, 2398476293847.9823749872349980].each do |i|
32
+ assert_equal wrap('real', i), Plist::Emit.dump(i, false).chomp
33
+ end
34
+ end
35
+
36
+ def test_booleans
37
+ assert_equal "<true/>", Plist::Emit.dump(true, false).chomp
38
+ assert_equal "<false/>", Plist::Emit.dump(false, false).chomp
39
+ end
40
+
41
+ def test_time
42
+ test_time = Time.now
43
+ assert_equal wrap('date', test_time.utc.strftime('%Y-%m-%dT%H:%M:%SZ')), Plist::Emit.dump(test_time, false).chomp
44
+ end
45
+
46
+ def test_dates
47
+ test_date = Date.today
48
+ test_datetime = DateTime.now
49
+
50
+ assert_equal wrap('date', test_date.strftime('%Y-%m-%dT%H:%M:%SZ')), Plist::Emit.dump(test_date, false).chomp
51
+ assert_equal wrap('date', test_datetime.strftime('%Y-%m-%dT%H:%M:%SZ')), Plist::Emit.dump(test_datetime, false).chomp
52
+ end
53
+ end
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'test/unit'
4
+ require 'plist'
5
+
6
+ class TestGeneratorCollections < Test::Unit::TestCase
7
+ def test_array
8
+ expected = <<END
9
+ <array>
10
+ <integer>1</integer>
11
+ <integer>2</integer>
12
+ <integer>3</integer>
13
+ </array>
14
+ END
15
+
16
+ assert_equal expected, [1,2,3].to_plist(false)
17
+ end
18
+
19
+ def test_empty_array
20
+ expected = <<END
21
+ <array/>
22
+ END
23
+
24
+ assert_equal expected, [].to_plist(false)
25
+ end
26
+
27
+ def test_hash
28
+ expected = <<END
29
+ <dict>
30
+ <key>abc</key>
31
+ <integer>123</integer>
32
+ <key>foo</key>
33
+ <string>bar</string>
34
+ </dict>
35
+ END
36
+ # thanks to recent changes in the generator code, hash keys are sorted before emission,
37
+ # so multi-element hash tests should be reliable. We're testing that here too.
38
+ assert_equal expected, {:foo => :bar, :abc => 123}.to_plist(false)
39
+ end
40
+
41
+ def test_empty_hash
42
+ expected = <<END
43
+ <dict/>
44
+ END
45
+
46
+ assert_equal expected, {}.to_plist(false)
47
+ end
48
+
49
+ def test_hash_with_array_element
50
+ expected = <<END
51
+ <dict>
52
+ <key>ary</key>
53
+ <array>
54
+ <integer>1</integer>
55
+ <string>b</string>
56
+ <string>3</string>
57
+ </array>
58
+ </dict>
59
+ END
60
+ assert_equal expected, {:ary => [1,:b,'3']}.to_plist(false)
61
+ end
62
+
63
+ def test_array_with_hash_element
64
+ expected = <<END
65
+ <array>
66
+ <dict>
67
+ <key>foo</key>
68
+ <string>bar</string>
69
+ </dict>
70
+ <string>b</string>
71
+ <integer>3</integer>
72
+ </array>
73
+ END
74
+
75
+ assert_equal expected, [{:foo => 'bar'}, :b, 3].to_plist(false)
76
+ end
77
+ end
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'test/unit'
4
+ require 'plist'
5
+
6
+ class TestParser < Test::Unit::TestCase
7
+ def test_Plist_parse_xml
8
+ result = Plist::parse_xml("test/assets/AlbumData.xml")
9
+
10
+ # dict
11
+ assert_kind_of( Hash, result )
12
+
13
+ expected = [
14
+ "List of Albums",
15
+ "Minor Version",
16
+ "Master Image List",
17
+ "Major Version",
18
+ "List of Keywords",
19
+ "Archive Path",
20
+ "List of Rolls",
21
+ "Application Version"
22
+ ]
23
+ assert_equal( expected.sort, result.keys.sort )
24
+
25
+ # array
26
+ assert_kind_of( Array, result["List of Rolls"] )
27
+ assert_equal( [ {"PhotoCount"=>1,
28
+ "KeyList"=>["7"],
29
+ "Parent"=>999000,
30
+ "Album Type"=>"Regular",
31
+ "AlbumName"=>"Roll 1",
32
+ "AlbumId"=>6}],
33
+ result["List of Rolls"] )
34
+
35
+ # string
36
+ assert_kind_of( String, result["Application Version"] )
37
+ assert_equal( "5.0.4 (263)", result["Application Version"] )
38
+
39
+ # integer
40
+ assert_kind_of( Integer, result["Major Version"] )
41
+ assert_equal( 2, result["Major Version"] )
42
+
43
+ # true
44
+ assert_kind_of( TrueClass, result["List of Albums"][0]["Master"] )
45
+ assert( result["List of Albums"][0]["Master"] )
46
+
47
+ # false
48
+ assert_kind_of( FalseClass, result["List of Albums"][1]["SlideShowUseTitles"] )
49
+ assert( ! result["List of Albums"][1]["SlideShowUseTitles"] )
50
+
51
+ end
52
+
53
+ # uncomment this test to work on speed optimization
54
+ #def test_load_something_big
55
+ # plist = Plist::parse_xml( "~/Pictures/iPhoto Library/AlbumData.xml" )
56
+ #end
57
+
58
+ # date fields are credited to
59
+ def test_date_fields
60
+ result = Plist::parse_xml("test/assets/Cookies.plist")
61
+ assert_kind_of( DateTime, result.first['Expires'] )
62
+ assert_equal DateTime.parse( "2007-10-25T12:36:35Z" ), result.first['Expires']
63
+ end
64
+
65
+ # bug fix for empty <key>
66
+ # reported by Matthias Peick <matthias@peick.de>
67
+ # reported and fixed by Frederik Seiffert <ego@frederikseiffert.de>
68
+ def test_empty_dict_key
69
+ data = Plist::parse_xml("test/assets/test_empty_key.plist");
70
+ assert_equal("2", data['key']['subkey'])
71
+ end
72
+
73
+ # bug fix for decoding entities
74
+ # reported by Matthias Peick <matthias@peick.de>
75
+ def test_decode_entities
76
+ data = Plist::parse_xml('<string>Fish &amp; Chips</string>')
77
+ assert_equal('Fish & Chips', data)
78
+ end
79
+
80
+ def test_comment_handling_and_empty_plist
81
+ assert_nothing_raised do
82
+ assert_nil( Plist::parse_xml( File.read('test/assets/commented.plist') ) )
83
+ end
84
+ end
85
+
86
+ def test_filename_or_xml_is_stringio
87
+ require 'stringio'
88
+
89
+ str = StringIO.new
90
+ data = Plist::parse_xml(str)
91
+
92
+ assert_nil data
93
+ end
94
+
95
+ end
96
+
97
+ __END__