1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
#include <cxxtest/TestSuite.h>
#include "common/serializer.h"
#include "common/stream.h"
class SerializerTestSuite : public CxxTest::TestSuite {
Common::SeekableReadStream *_inStreamV1;
Common::SeekableReadStream *_inStreamV2;
public:
void setUp() {
// Our pseudo data format is as follows:
// * magic id - string "MAGI"
// * Version - uint32, LE
// * uint32, LE (available in v2 onward)
// * uint16, BE (available in v1 onward)
// * sint16, LE (available only in v1)
// * byte (always available)
static const byte contents_v1[] = {
'M', 'A', 'G', 'I', // magic id
0x01, 0x00, 0x00, 0x00, // Version
0x06, 0x07, // uint16, BE (available in v1 onward)
0xfe, 0xff, // sint16, LE (available only in v1)
0x0a // byte (always available)
};
static const byte contents_v2[] = {
'M', 'A', 'G', 'I', // magic id
0x02, 0x00, 0x00, 0x00, // Version
0x02, 0x03, 0x04, 0x05, // uint32, LE (available in v2 onward)
0x06, 0x07, // uint16, BE (available in v1 onward)
0x0a // byte (always available)
};
_inStreamV1 = new Common::MemoryReadStream(contents_v1, sizeof(contents_v1));
_inStreamV2 = new Common::MemoryReadStream(contents_v2, sizeof(contents_v2));
}
void tearDown() {
delete _inStreamV1;
delete _inStreamV2;
}
// A method which reads a v1 file
void readVersioned_v1(Common::SeekableReadStream *stream, Common::Serializer::Version version) {
Common::Serializer ser(stream, 0);
TS_ASSERT(ser.matchBytes("MAGI", 4));
TS_ASSERT(ser.syncVersion(1));
TS_ASSERT_EQUALS(ser.getVersion(), version);
uint32 tmp = 0;
ser.syncAsUint16BE(tmp, Common::Serializer::Version(1));
TS_ASSERT_EQUALS(tmp, (uint16)0x0607);
ser.syncAsSint16LE(tmp, Common::Serializer::Version(1));
TS_ASSERT_EQUALS((int16)tmp, -2);
ser.syncAsByte(tmp);
TS_ASSERT_EQUALS(tmp, (uint8)0x0a);
}
// A method which reads a v2 file
void readVersioned_v2(Common::SeekableReadStream *stream, Common::Serializer::Version version) {
Common::Serializer ser(stream, 0);
TS_ASSERT(ser.matchBytes("MAGI", 4));
TS_ASSERT(ser.syncVersion(2));
TS_ASSERT_EQUALS(ser.getVersion(), version);
uint32 tmp;
// Read a value only available starting with v2.
// Thus if we load an old save, it must be
// manually set. To simplify that, no sync method should
// modify the value passed to it if nothing was read!
tmp = 0x12345678;
ser.syncAsUint32LE(tmp, Common::Serializer::Version(2));
if (ser.getVersion() < 2) {
TS_ASSERT_EQUALS(tmp, (uint32)0x12345678);
} else {
TS_ASSERT_EQUALS(tmp, (uint32)0x05040302);
}
ser.syncAsUint16BE(tmp, Common::Serializer::Version(1));
TS_ASSERT_EQUALS(tmp, (uint32)0x0607);
// Skip over obsolete data
ser.skip(2, Common::Serializer::Version(1), Common::Serializer::Version(1));
ser.syncAsByte(tmp);
TS_ASSERT_EQUALS(tmp, (uint8)0x0a);
}
void test_read_v1_as_v1() {
readVersioned_v1(_inStreamV1, 1);
}
// There is no test_read_v2_as_v1() because a v1 parser cannot possibly
// read v2 data correctly. It should instead error out if it
// detects a version newer than its current version.
void test_read_v1_as_v2() {
readVersioned_v2(_inStreamV1, 1);
}
void test_read_v2_as_v2() {
readVersioned_v2(_inStreamV2, 2);
}
};
|