xref: /qemu/tests/unit/test-xbzrle.c (revision c3bef3b4)
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 int (*xbzrle_encode_buffer_func)(uint8_t *, uint8_t *, int,
20      uint8_t *, int) = xbzrle_encode_buffer;
21 #if defined(CONFIG_AVX512BW_OPT)
22 #include "qemu/cpuid.h"
23 static void __attribute__((constructor)) init_cpu_flag(void)
24 {
25     unsigned max = __get_cpuid_max(0, NULL);
26     int a, b, c, d;
27     if (max >= 1) {
28         __cpuid(1, a, b, c, d);
29          /* We must check that AVX is not just available, but usable.  */
30         if ((c & bit_OSXSAVE) && (c & bit_AVX) && max >= 7) {
31             int bv;
32             __asm("xgetbv" : "=a"(bv), "=d"(d) : "c"(0));
33             __cpuid_count(7, 0, a, b, c, d);
34            /* 0xe6:
35             *  XCR0[7:5] = 111b (OPMASK state, upper 256-bit of ZMM0-ZMM15
36             *                    and ZMM16-ZMM31 state are enabled by OS)
37             *  XCR0[2:1] = 11b (XMM state and YMM state are enabled by OS)
38             */
39             if ((bv & 0xe6) == 0xe6 && (b & bit_AVX512BW)) {
40                 xbzrle_encode_buffer_func = xbzrle_encode_buffer_avx512;
41             }
42         }
43     }
44     return ;
45 }
46 #endif
47 
48 static void test_uleb(void)
49 {
50     uint32_t i, val;
51     uint8_t buf[2];
52     int encode_ret, decode_ret;
53 
54     for (i = 0; i <= 0x3fff; i++) {
55         encode_ret = uleb128_encode_small(&buf[0], i);
56         decode_ret = uleb128_decode_small(&buf[0], &val);
57         g_assert(encode_ret == decode_ret);
58         g_assert(i == val);
59     }
60 
61     /* decode invalid value */
62     buf[0] = 0x80;
63     buf[1] = 0x80;
64 
65     decode_ret = uleb128_decode_small(&buf[0], &val);
66     g_assert(decode_ret == -1);
67     g_assert(val == 0);
68 }
69 
70 static void test_encode_decode_zero(void)
71 {
72     uint8_t *buffer = g_malloc0(XBZRLE_PAGE_SIZE);
73     uint8_t *compressed = g_malloc0(XBZRLE_PAGE_SIZE);
74     int i = 0;
75     int dlen = 0;
76     int diff_len = g_test_rand_int_range(0, XBZRLE_PAGE_SIZE - 1006);
77 
78     for (i = diff_len; i > 0; i--) {
79         buffer[1000 + i] = i;
80     }
81 
82     buffer[1000 + diff_len + 3] = 103;
83     buffer[1000 + diff_len + 5] = 105;
84 
85     /* encode zero page */
86     dlen = xbzrle_encode_buffer_func(buffer, buffer, XBZRLE_PAGE_SIZE, compressed,
87                        XBZRLE_PAGE_SIZE);
88     g_assert(dlen == 0);
89 
90     g_free(buffer);
91     g_free(compressed);
92 }
93 
94 static void test_encode_decode_unchanged(void)
95 {
96     uint8_t *compressed = g_malloc0(XBZRLE_PAGE_SIZE);
97     uint8_t *test = g_malloc0(XBZRLE_PAGE_SIZE);
98     int i = 0;
99     int dlen = 0;
100     int diff_len = g_test_rand_int_range(0, XBZRLE_PAGE_SIZE - 1006);
101 
102     for (i = diff_len; i > 0; i--) {
103         test[1000 + i] = i + 4;
104     }
105 
106     test[1000 + diff_len + 3] = 107;
107     test[1000 + diff_len + 5] = 109;
108 
109     /* test unchanged buffer */
110     dlen = xbzrle_encode_buffer_func(test, test, XBZRLE_PAGE_SIZE, compressed,
111                                 XBZRLE_PAGE_SIZE);
112     g_assert(dlen == 0);
113 
114     g_free(test);
115     g_free(compressed);
116 }
117 
118 static void test_encode_decode_1_byte(void)
119 {
120     uint8_t *buffer = g_malloc0(XBZRLE_PAGE_SIZE);
121     uint8_t *test = g_malloc0(XBZRLE_PAGE_SIZE);
122     uint8_t *compressed = g_malloc(XBZRLE_PAGE_SIZE);
123     int dlen = 0, rc = 0;
124     uint8_t buf[2];
125 
126     test[XBZRLE_PAGE_SIZE - 1] = 1;
127 
128     dlen = xbzrle_encode_buffer_func(buffer, test, XBZRLE_PAGE_SIZE, compressed,
129                        XBZRLE_PAGE_SIZE);
130     g_assert(dlen == (uleb128_encode_small(&buf[0], 4095) + 2));
131 
132     rc = xbzrle_decode_buffer(compressed, dlen, buffer, XBZRLE_PAGE_SIZE);
133     g_assert(rc == XBZRLE_PAGE_SIZE);
134     g_assert(memcmp(test, buffer, XBZRLE_PAGE_SIZE) == 0);
135 
136     g_free(buffer);
137     g_free(compressed);
138     g_free(test);
139 }
140 
141 static void test_encode_decode_overflow(void)
142 {
143     uint8_t *compressed = g_malloc0(XBZRLE_PAGE_SIZE);
144     uint8_t *test = g_malloc0(XBZRLE_PAGE_SIZE);
145     uint8_t *buffer = g_malloc0(XBZRLE_PAGE_SIZE);
146     int i = 0, rc = 0;
147 
148     for (i = 0; i < XBZRLE_PAGE_SIZE / 2 - 1; i++) {
149         test[i * 2] = 1;
150     }
151 
152     /* encode overflow */
153     rc = xbzrle_encode_buffer_func(buffer, test, XBZRLE_PAGE_SIZE, compressed,
154                               XBZRLE_PAGE_SIZE);
155     g_assert(rc == -1);
156 
157     g_free(buffer);
158     g_free(compressed);
159     g_free(test);
160 }
161 
162 static void encode_decode_range(void)
163 {
164     uint8_t *buffer = g_malloc0(XBZRLE_PAGE_SIZE);
165     uint8_t *compressed = g_malloc(XBZRLE_PAGE_SIZE);
166     uint8_t *test = g_malloc0(XBZRLE_PAGE_SIZE);
167     int i = 0, rc = 0;
168     int dlen = 0;
169 
170     int diff_len = g_test_rand_int_range(0, XBZRLE_PAGE_SIZE - 1006);
171 
172     for (i = diff_len; i > 0; i--) {
173         buffer[1000 + i] = i;
174         test[1000 + i] = i + 4;
175     }
176 
177     buffer[1000 + diff_len + 3] = 103;
178     test[1000 + diff_len + 3] = 107;
179 
180     buffer[1000 + diff_len + 5] = 105;
181     test[1000 + diff_len + 5] = 109;
182 
183     /* test encode/decode */
184     dlen = xbzrle_encode_buffer_func(test, buffer, XBZRLE_PAGE_SIZE, compressed,
185                                 XBZRLE_PAGE_SIZE);
186 
187     rc = xbzrle_decode_buffer(compressed, dlen, test, XBZRLE_PAGE_SIZE);
188     g_assert(rc < XBZRLE_PAGE_SIZE);
189     g_assert(memcmp(test, buffer, XBZRLE_PAGE_SIZE) == 0);
190 
191     g_free(buffer);
192     g_free(compressed);
193     g_free(test);
194 }
195 
196 static void test_encode_decode(void)
197 {
198     int i;
199 
200     for (i = 0; i < 10000; i++) {
201         encode_decode_range();
202     }
203 }
204 
205 int main(int argc, char **argv)
206 {
207     g_test_init(&argc, &argv, NULL);
208     g_test_rand_int();
209     g_test_add_func("/xbzrle/uleb", test_uleb);
210     g_test_add_func("/xbzrle/encode_decode_zero", test_encode_decode_zero);
211     g_test_add_func("/xbzrle/encode_decode_unchanged",
212                     test_encode_decode_unchanged);
213     g_test_add_func("/xbzrle/encode_decode_1_byte", test_encode_decode_1_byte);
214     g_test_add_func("/xbzrle/encode_decode_overflow",
215                     test_encode_decode_overflow);
216     g_test_add_func("/xbzrle/encode_decode", test_encode_decode);
217 
218     return g_test_run();
219 }
220