Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aos
GitHub Repository: aos/firecracker
Path: blob/main/src/snapshot/tests/test.rs
1964 views
1
// Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
// SPDX-License-Identifier: Apache-2.0
3
use snapshot::{Error, Snapshot};
4
use versionize::{VersionMap, Versionize, VersionizeError, VersionizeResult};
5
use versionize_derive::Versionize;
6
7
#[derive(Debug, PartialEq, Versionize)]
8
pub enum TestState {
9
Zero,
10
One(u32),
11
#[version(start = 2, default_fn = "default_state_two")]
12
Two(u64),
13
}
14
15
impl TestState {
16
fn default_state_two(&self, target_version: u16) -> VersionizeResult<TestState> {
17
match target_version {
18
1 => Ok(TestState::One(2)),
19
i => Err(VersionizeError::Serialize(format!(
20
"Unknown target version: {}",
21
i
22
))),
23
}
24
}
25
}
26
27
#[derive(Debug, PartialEq, Versionize)]
28
pub struct A {
29
a: u32,
30
#[version(start = 1, end = 2)]
31
b: Option<TestState>,
32
#[version(start = 2, default_fn = "default_c")]
33
c: String,
34
}
35
36
impl A {
37
fn default_c(_source_version: u16) -> String {
38
"some_string".to_owned()
39
}
40
}
41
42
#[test]
43
fn test_hardcoded_snapshot_deserialization() {
44
// We are testing representation compatibility between versions, at the `snapshot` crate
45
// level, by checking that only the version number and the newly added/removed fields changes
46
// between versions are reflected in the hardcoded snapshot.
47
48
#[rustfmt::skip]
49
let v1_hardcoded_snapshot: &[u8] = &[
50
// This blob consists of the following: magic_id (8 bytes),
51
0x01, 0x00,
52
#[cfg(target_arch = "aarch64")]
53
0xAA,
54
#[cfg(target_arch = "aarch64")]
55
0xAA,
56
#[cfg(target_arch = "x86_64")]
57
0x64,
58
#[cfg(target_arch = "x86_64")]
59
0x86,
60
0x84, 0x19, 0x10, 0x07,
61
// target version (2 bytes) +
62
0x01, 0x00,
63
// `a` field +
64
0x10, 0x00, 0x00, 0x00,
65
// `b` field: Option variant type (1 byte) + inner enum variant type (4 bytes)
66
// + inner enum value (4 bytes).
67
0x01, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
68
];
69
70
#[rustfmt::skip]
71
let v2_hardcoded_snapshot: &[u8] = &[
72
0x01,
73
0x00,
74
#[cfg(target_arch = "aarch64")]
75
0xAA,
76
#[cfg(target_arch = "aarch64")]
77
0xAA,
78
#[cfg(target_arch = "x86_64")]
79
0x64,
80
#[cfg(target_arch = "x86_64")]
81
0x86, 0x84, 0x19, 0x10, 0x07,
82
// Version 2 +
83
0x02, 0x00,
84
// `a` field +
85
0x10, 0x00, 0x00, 0x00,
86
// `c` field: String len (8 bytes) + actual String; the Option field is not available at v2.
87
0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x61, 0x6E, 0x64, 0x6F, 0x6D,
88
];
89
90
let mut vm = VersionMap::new();
91
vm.new_version()
92
.set_type_version(A::type_id(), 2)
93
.set_type_version(TestState::type_id(), 2);
94
95
let mut snapshot_blob = v1_hardcoded_snapshot;
96
97
let mut restored_struct: A = Snapshot::unchecked_load(&mut snapshot_blob, vm.clone()).unwrap();
98
99
let mut expected_struct = A {
100
a: 16u32,
101
b: Some(TestState::One(2)),
102
c: "some_string".to_owned(),
103
};
104
105
assert_eq!(restored_struct, expected_struct);
106
107
snapshot_blob = v2_hardcoded_snapshot;
108
109
restored_struct = Snapshot::unchecked_load(&mut snapshot_blob, vm.clone()).unwrap();
110
111
expected_struct = A {
112
a: 16u32,
113
b: None,
114
c: "random".to_owned(),
115
};
116
117
assert_eq!(restored_struct, expected_struct);
118
}
119
120
#[test]
121
fn test_invalid_format_version() {
122
#[rustfmt::skip]
123
let invalid_format_snap: &[u8] = &[
124
// This blob consists of the following: magic_id (8 bytes),
125
0xAA, 0xAA,
126
#[cfg(target_arch = "aarch64")]
127
0xAA,
128
#[cfg(target_arch = "aarch64")]
129
0xAA,
130
#[cfg(target_arch = "x86_64")]
131
0x64,
132
#[cfg(target_arch = "x86_64")]
133
0x86,
134
0x84, 0x19, 0x10, 0x07,
135
// target version (2 bytes) +
136
0x01, 0x00,
137
// `a` field +
138
0x10, 0x00, 0x00, 0x00,
139
// `b` field: Option variant type (1 byte) + inner enum variant type (4 bytes)
140
// + inner enum value (4 bytes).
141
0x01, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
142
];
143
144
let mut result: Result<A, Error> =
145
Snapshot::unchecked_load(&mut invalid_format_snap.as_ref(), VersionMap::new());
146
let mut expected_err = Error::InvalidFormatVersion(0xAAAA);
147
assert_eq!(result.unwrap_err(), expected_err);
148
149
#[rustfmt::skip]
150
let null_format_snap: &[u8] = &[
151
// This blob consists of the following: magic_id (8 bytes),
152
0x00, 0x00,
153
#[cfg(target_arch = "aarch64")]
154
0xAA,
155
#[cfg(target_arch = "aarch64")]
156
0xAA,
157
#[cfg(target_arch = "x86_64")]
158
0x64,
159
#[cfg(target_arch = "x86_64")]
160
0x86,
161
0x84, 0x19, 0x10, 0x07,
162
// target version (2 bytes) +
163
0x01, 0x00,
164
// `a` field +
165
0x10, 0x00, 0x00, 0x00,
166
// `b` field: Option variant type (1 byte) + inner enum variant type (4 bytes)
167
// + inner enum value (4 bytes).
168
0x01, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
169
];
170
171
result = Snapshot::unchecked_load(&mut null_format_snap.as_ref(), VersionMap::new());
172
expected_err = Error::InvalidFormatVersion(0);
173
assert_eq!(result.unwrap_err(), expected_err);
174
}
175
176
#[test]
177
fn test_invalid_data_version() {
178
#[rustfmt::skip]
179
let invalid_data_version_snap: &[u8] = &[
180
// This blob consists of the following: magic_id (8 bytes),
181
0x01, 0x00,
182
#[cfg(target_arch = "aarch64")]
183
0xAA,
184
#[cfg(target_arch = "aarch64")]
185
0xAA,
186
#[cfg(target_arch = "x86_64")]
187
0x64,
188
#[cfg(target_arch = "x86_64")]
189
0x86,
190
0x84, 0x19, 0x10, 0x07,
191
// target version (2 bytes) +
192
0xAA, 0xAA,
193
// `a` field +
194
0x10, 0x00, 0x00, 0x00,
195
// `b` field: Option variant type (1 byte) + inner enum variant type (4 bytes)
196
// + inner enum value (4 bytes).
197
0x01, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
198
];
199
let mut result: Result<A, Error> =
200
Snapshot::unchecked_load(&mut invalid_data_version_snap.as_ref(), VersionMap::new());
201
let mut expected_err = Error::InvalidDataVersion(0xAAAA);
202
assert_eq!(result.unwrap_err(), expected_err);
203
204
#[rustfmt::skip]
205
let null_data_version_snap: &[u8] = &[
206
// This blob consists of the following: magic_id (8 bytes),
207
0x01, 0x00,
208
#[cfg(target_arch = "aarch64")]
209
0xAA,
210
#[cfg(target_arch = "aarch64")]
211
0xAA,
212
#[cfg(target_arch = "x86_64")]
213
0x64,
214
#[cfg(target_arch = "x86_64")]
215
0x86,
216
0x84, 0x19, 0x10, 0x07,
217
// target version (2 bytes) +
218
0x00, 0x00,
219
// `a` field +
220
0x10, 0x00, 0x00, 0x00,
221
// `b` field: Option variant type (1 byte) + inner enum variant type (4 bytes)
222
// + inner enum value (4 bytes).
223
0x01, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
224
];
225
result = Snapshot::unchecked_load(&mut null_data_version_snap.as_ref(), VersionMap::new());
226
expected_err = Error::InvalidDataVersion(0);
227
assert_eq!(result.unwrap_err(), expected_err);
228
}
229
230