static void encode_decode_range(void) { uint8_t *buffer = g_malloc0(PAGE_SIZE); uint8_t *compressed = g_malloc(PAGE_SIZE); uint8_t *test = g_malloc0(PAGE_SIZE); int i = 0, rc = 0; int dlen = 0; int diff_len = g_test_rand_int_range(0, PAGE_SIZE - 1006); for (i = diff_len; i > 0; i--) { buffer[1000 + i] = i; test[1000 + i] = i + 4; } buffer[1000 + diff_len + 3] = 103; test[1000 + diff_len + 3] = 107; buffer[1000 + diff_len + 5] = 105; test[1000 + diff_len + 5] = 109; /* test encode/decode */ dlen = xbzrle_encode_buffer(test, buffer, PAGE_SIZE, compressed, PAGE_SIZE); rc = xbzrle_decode_buffer(compressed, dlen, test, PAGE_SIZE); g_assert(rc < PAGE_SIZE); g_assert(memcmp(test, buffer, PAGE_SIZE) == 0); g_free(buffer); g_free(compressed); g_free(test); }
static int save_xbzrle_page(QEMUFile *f, uint8_t **current_data, ram_addr_t current_addr, RAMBlock *block, ram_addr_t offset, int cont, bool last_stage) { int encoded_len = 0, bytes_sent = -1; uint8_t *prev_cached_page; if (!cache_is_cached(XBZRLE.cache, current_addr)) { acct_info.xbzrle_cache_miss++; if (!last_stage) { if (cache_insert(XBZRLE.cache, current_addr, *current_data) == -1) { return -1; } else { /* update *current_data when the page has been inserted into cache */ *current_data = get_cached_data(XBZRLE.cache, current_addr); } } return -1; } prev_cached_page = get_cached_data(XBZRLE.cache, current_addr); /* save current buffer into memory */ memcpy(XBZRLE.current_buf, *current_data, TARGET_PAGE_SIZE); /* XBZRLE encoding (if there is no overflow) */ encoded_len = xbzrle_encode_buffer(prev_cached_page, XBZRLE.current_buf, TARGET_PAGE_SIZE, XBZRLE.encoded_buf, TARGET_PAGE_SIZE); if (encoded_len == 0) { DPRINTF("Skipping unmodified page\n"); return 0; } else if (encoded_len == -1) { DPRINTF("Overflow\n"); acct_info.xbzrle_overflows++; /* update data in the cache */ if (!last_stage) { memcpy(prev_cached_page, *current_data, TARGET_PAGE_SIZE); *current_data = prev_cached_page; } return -1; } /* we need to update the data in the cache, in order to get the same data */ if (!last_stage) { memcpy(prev_cached_page, XBZRLE.current_buf, TARGET_PAGE_SIZE); } /* Send XBZRLE based compressed page */ bytes_sent = save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_XBZRLE); qemu_put_byte(f, ENCODING_FLAG_XBZRLE); qemu_put_be16(f, encoded_len); qemu_put_buffer(f, XBZRLE.encoded_buf, encoded_len); bytes_sent += encoded_len + 1 + 2; acct_info.xbzrle_pages++; acct_info.xbzrle_bytes += bytes_sent; return bytes_sent; }
static void test_encode_decode_overflow(void) { uint8_t *compressed = g_malloc0(PAGE_SIZE); uint8_t *test = g_malloc0(PAGE_SIZE); uint8_t *buffer = g_malloc0(PAGE_SIZE); int i = 0, rc = 0; for (i = 0; i < PAGE_SIZE / 2 - 1; i++) { test[i * 2] = 1; } /* encode overflow */ rc = xbzrle_encode_buffer(buffer, test, PAGE_SIZE, compressed, PAGE_SIZE); g_assert(rc == -1); g_free(buffer); g_free(compressed); g_free(test); }
static void test_encode_decode_1_byte(void) { uint8_t *buffer = g_malloc0(PAGE_SIZE); uint8_t *test = g_malloc0(PAGE_SIZE); uint8_t *compressed = g_malloc(PAGE_SIZE); int dlen = 0, rc = 0; uint8_t buf[2]; test[PAGE_SIZE - 1] = 1; dlen = xbzrle_encode_buffer(buffer, test, PAGE_SIZE, compressed, PAGE_SIZE); g_assert(dlen == (uleb128_encode_small(&buf[0], 4095) + 2)); rc = xbzrle_decode_buffer(compressed, dlen, buffer, PAGE_SIZE); g_assert(rc == PAGE_SIZE); g_assert(memcmp(test, buffer, PAGE_SIZE) == 0); g_free(buffer); g_free(compressed); g_free(test); }
static void test_encode_decode_unchanged(void) { uint8_t *compressed = g_malloc0(PAGE_SIZE); uint8_t *test = g_malloc0(PAGE_SIZE); int i = 0; int dlen = 0; int diff_len = g_test_rand_int_range(0, PAGE_SIZE - 1006); for (i = diff_len; i > 0; i--) { test[1000 + i] = i + 4; } test[1000 + diff_len + 3] = 107; test[1000 + diff_len + 5] = 109; /* test unchanged buffer */ dlen = xbzrle_encode_buffer(test, test, PAGE_SIZE, compressed, PAGE_SIZE); g_assert(dlen == 0); g_free(test); g_free(compressed); }
static void test_encode_decode_zero(void) { uint8_t *buffer = g_malloc0(PAGE_SIZE); uint8_t *compressed = g_malloc0(PAGE_SIZE); int i = 0; int dlen = 0; int diff_len = g_test_rand_int_range(0, PAGE_SIZE - 1006); for (i = diff_len; i > 0; i--) { buffer[1000 + i] = i; } buffer[1000 + diff_len + 3] = 103; buffer[1000 + diff_len + 5] = 105; /* encode zero page */ dlen = xbzrle_encode_buffer(buffer, buffer, PAGE_SIZE, compressed, PAGE_SIZE); g_assert(dlen == 0); g_free(buffer); g_free(compressed); }