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