xref: /qemu/tests/unit/test-xbzrle.c (revision 78f314cf)
1 /*
2  * Xor Based Zero Run Length Encoding unit tests.
3  *
4  * Copyright 2013 Red Hat, Inc. and/or its affiliates
5  *
6  * Authors:
7  *  Orit Wasserman  <owasserm@redhat.com>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2 or later.
10  * See the COPYING file in the top-level directory.
11  *
12  */
13 #include "qemu/osdep.h"
14 #include "qemu/cutils.h"
15 #include "../migration/xbzrle.h"
16 
17 #define XBZRLE_PAGE_SIZE 4096
18 
19 static void test_uleb(void)
20 {
21     uint32_t i, val;
22     uint8_t buf[2];
23     int encode_ret, decode_ret;
24 
25     for (i = 0; i <= 0x3fff; i++) {
26         encode_ret = uleb128_encode_small(&buf[0], i);
27         decode_ret = uleb128_decode_small(&buf[0], &val);
28         g_assert(encode_ret == decode_ret);
29         g_assert(i == val);
30     }
31 
32     /* decode invalid value */
33     buf[0] = 0x80;
34     buf[1] = 0x80;
35 
36     decode_ret = uleb128_decode_small(&buf[0], &val);
37     g_assert(decode_ret == -1);
38     g_assert(val == 0);
39 }
40 
41 static void test_encode_decode_zero(void)
42 {
43     uint8_t *buffer = g_malloc0(XBZRLE_PAGE_SIZE);
44     uint8_t *compressed = g_malloc0(XBZRLE_PAGE_SIZE);
45     int i = 0;
46     int dlen = 0;
47     int diff_len = g_test_rand_int_range(0, XBZRLE_PAGE_SIZE - 1006);
48 
49     for (i = diff_len; i > 0; i--) {
50         buffer[1000 + i] = i;
51     }
52 
53     buffer[1000 + diff_len + 3] = 103;
54     buffer[1000 + diff_len + 5] = 105;
55 
56     /* encode zero page */
57     dlen = xbzrle_encode_buffer(buffer, buffer, XBZRLE_PAGE_SIZE,
58                                 compressed, XBZRLE_PAGE_SIZE);
59     g_assert(dlen == 0);
60 
61     g_free(buffer);
62     g_free(compressed);
63 }
64 
65 static void test_encode_decode_unchanged(void)
66 {
67     uint8_t *compressed = g_malloc0(XBZRLE_PAGE_SIZE);
68     uint8_t *test = g_malloc0(XBZRLE_PAGE_SIZE);
69     int i = 0;
70     int dlen = 0;
71     int diff_len = g_test_rand_int_range(0, XBZRLE_PAGE_SIZE - 1006);
72 
73     for (i = diff_len; i > 0; i--) {
74         test[1000 + i] = i + 4;
75     }
76 
77     test[1000 + diff_len + 3] = 107;
78     test[1000 + diff_len + 5] = 109;
79 
80     /* test unchanged buffer */
81     dlen = xbzrle_encode_buffer(test, test, XBZRLE_PAGE_SIZE,
82                                 compressed, XBZRLE_PAGE_SIZE);
83     g_assert(dlen == 0);
84 
85     g_free(test);
86     g_free(compressed);
87 }
88 
89 static void test_encode_decode_1_byte(void)
90 {
91     uint8_t *buffer = g_malloc0(XBZRLE_PAGE_SIZE);
92     uint8_t *test = g_malloc0(XBZRLE_PAGE_SIZE);
93     uint8_t *compressed = g_malloc(XBZRLE_PAGE_SIZE);
94     int dlen = 0, rc = 0;
95     uint8_t buf[2];
96 
97     test[XBZRLE_PAGE_SIZE - 1] = 1;
98 
99     dlen = xbzrle_encode_buffer(buffer, test, XBZRLE_PAGE_SIZE,
100                                 compressed, XBZRLE_PAGE_SIZE);
101     g_assert(dlen == (uleb128_encode_small(&buf[0], 4095) + 2));
102 
103     rc = xbzrle_decode_buffer(compressed, dlen, buffer, XBZRLE_PAGE_SIZE);
104     g_assert(rc == XBZRLE_PAGE_SIZE);
105     g_assert(memcmp(test, buffer, XBZRLE_PAGE_SIZE) == 0);
106 
107     g_free(buffer);
108     g_free(compressed);
109     g_free(test);
110 }
111 
112 static void test_encode_decode_overflow(void)
113 {
114     uint8_t *compressed = g_malloc0(XBZRLE_PAGE_SIZE);
115     uint8_t *test = g_malloc0(XBZRLE_PAGE_SIZE);
116     uint8_t *buffer = g_malloc0(XBZRLE_PAGE_SIZE);
117     int i = 0, rc = 0;
118 
119     for (i = 0; i < XBZRLE_PAGE_SIZE / 2 - 1; i++) {
120         test[i * 2] = 1;
121     }
122 
123     /* encode overflow */
124     rc = xbzrle_encode_buffer(buffer, test, XBZRLE_PAGE_SIZE,
125                               compressed, XBZRLE_PAGE_SIZE);
126     g_assert(rc == -1);
127 
128     g_free(buffer);
129     g_free(compressed);
130     g_free(test);
131 }
132 
133 static void encode_decode_range(void)
134 {
135     uint8_t *buffer = g_malloc0(XBZRLE_PAGE_SIZE);
136     uint8_t *compressed = g_malloc(XBZRLE_PAGE_SIZE);
137     uint8_t *test = g_malloc0(XBZRLE_PAGE_SIZE);
138     int i = 0, rc = 0;
139     int dlen = 0;
140 
141     int diff_len = g_test_rand_int_range(0, XBZRLE_PAGE_SIZE - 1006);
142 
143     for (i = diff_len; i > 0; i--) {
144         buffer[1000 + i] = i;
145         test[1000 + i] = i + 4;
146     }
147 
148     buffer[1000 + diff_len + 3] = 103;
149     test[1000 + diff_len + 3] = 107;
150 
151     buffer[1000 + diff_len + 5] = 105;
152     test[1000 + diff_len + 5] = 109;
153 
154     /* test encode/decode */
155     dlen = xbzrle_encode_buffer(test, buffer, XBZRLE_PAGE_SIZE,
156                                 compressed, XBZRLE_PAGE_SIZE);
157 
158     rc = xbzrle_decode_buffer(compressed, dlen, test, XBZRLE_PAGE_SIZE);
159     g_assert(rc < XBZRLE_PAGE_SIZE);
160     g_assert(memcmp(test, buffer, XBZRLE_PAGE_SIZE) == 0);
161 
162     g_free(buffer);
163     g_free(compressed);
164     g_free(test);
165 }
166 
167 static void test_encode_decode(void)
168 {
169     int i;
170 
171     for (i = 0; i < 10000; i++) {
172         encode_decode_range();
173     }
174 }
175 
176 int main(int argc, char **argv)
177 {
178     g_test_init(&argc, &argv, NULL);
179     g_test_rand_int();
180     g_test_add_func("/xbzrle/uleb", test_uleb);
181     g_test_add_func("/xbzrle/encode_decode_zero", test_encode_decode_zero);
182     g_test_add_func("/xbzrle/encode_decode_unchanged",
183                     test_encode_decode_unchanged);
184     g_test_add_func("/xbzrle/encode_decode_1_byte", test_encode_decode_1_byte);
185     g_test_add_func("/xbzrle/encode_decode_overflow",
186                     test_encode_decode_overflow);
187     g_test_add_func("/xbzrle/encode_decode", test_encode_decode);
188 
189     return g_test_run();
190 }
191