2017-09-16 11:32:20 -05:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
|
|
|
/*
|
|
|
|
* This file is part of the LibreOffice project.
|
|
|
|
*
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
*/
|
|
|
|
|
2017-12-20 07:06:26 -06:00
|
|
|
#include <config.h>
|
2017-09-16 11:32:20 -05:00
|
|
|
|
2020-01-20 10:45:53 -06:00
|
|
|
#include <test/lokassert.hpp>
|
2017-09-16 11:32:20 -05:00
|
|
|
|
2017-12-20 07:06:26 -06:00
|
|
|
#include <Delta.hpp>
|
|
|
|
#include <Util.hpp>
|
|
|
|
#include <Png.hpp>
|
2017-09-16 11:32:20 -05:00
|
|
|
|
|
|
|
/// Delta unit-tests.
|
|
|
|
class DeltaTests : public CPPUNIT_NS::TestFixture
|
|
|
|
{
|
|
|
|
CPPUNIT_TEST_SUITE(DeltaTests);
|
|
|
|
|
|
|
|
CPPUNIT_TEST(testDeltaSequence);
|
|
|
|
CPPUNIT_TEST(testRandomDeltas);
|
|
|
|
|
|
|
|
CPPUNIT_TEST_SUITE_END();
|
|
|
|
|
|
|
|
void testDeltaSequence();
|
|
|
|
void testRandomDeltas();
|
|
|
|
|
|
|
|
std::vector<char> loadPng(const char *relpath,
|
|
|
|
png_uint_32& height,
|
|
|
|
png_uint_32& width,
|
|
|
|
png_uint_32& rowBytes)
|
|
|
|
{
|
|
|
|
std::ifstream file(relpath);
|
|
|
|
std::stringstream buffer;
|
|
|
|
buffer << file.rdbuf();
|
|
|
|
file.close();
|
|
|
|
std::vector<png_bytep> rows =
|
|
|
|
Png::decodePNG(buffer, height, width, rowBytes);
|
|
|
|
std::vector<char> output;
|
|
|
|
for (png_uint_32 y = 0; y < height; ++y)
|
|
|
|
{
|
|
|
|
for (png_uint_32 i = 0; i < width * 4; ++i)
|
|
|
|
{
|
|
|
|
output.push_back(rows[y][i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<char> applyDelta(
|
|
|
|
const std::vector<char> &pixmap,
|
|
|
|
png_uint_32 width, png_uint_32 height,
|
|
|
|
const std::vector<char> &delta);
|
|
|
|
|
|
|
|
void assertEqual(const std::vector<char> &a,
|
2017-09-28 03:45:46 -05:00
|
|
|
const std::vector<char> &b,
|
|
|
|
int width, int height);
|
2017-09-16 11:32:20 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
// Quick hack for debugging
|
|
|
|
std::vector<char> DeltaTests::applyDelta(
|
|
|
|
const std::vector<char> &pixmap,
|
2017-09-28 03:45:46 -05:00
|
|
|
png_uint_32 width, png_uint_32 height,
|
2017-09-16 11:32:20 -05:00
|
|
|
const std::vector<char> &delta)
|
|
|
|
{
|
2020-01-20 10:45:53 -06:00
|
|
|
LOK_ASSERT(delta.size() >= 4);
|
|
|
|
LOK_ASSERT(delta[0] == 'D');
|
2017-09-16 11:32:20 -05:00
|
|
|
|
2017-09-28 03:45:46 -05:00
|
|
|
// start with the same state.
|
2017-09-16 11:32:20 -05:00
|
|
|
std::vector<char> output = pixmap;
|
2020-01-20 10:45:53 -06:00
|
|
|
LOK_ASSERT_EQUAL(output.size(), size_t(pixmap.size()));
|
|
|
|
LOK_ASSERT_EQUAL(output.size(), size_t(width * height * 4));
|
2017-09-28 03:45:46 -05:00
|
|
|
|
|
|
|
size_t offset = 0, i;
|
|
|
|
for (i = 1; i < delta.size() && offset < output.size();)
|
2017-09-16 11:32:20 -05:00
|
|
|
{
|
2017-09-28 03:45:46 -05:00
|
|
|
switch (delta[i])
|
|
|
|
{
|
|
|
|
case 'c': // copy row.
|
|
|
|
{
|
2017-10-23 14:59:10 -05:00
|
|
|
int count = (uint8_t)(delta[i+1]);
|
|
|
|
int srcRow = (uint8_t)(delta[i+2]);
|
|
|
|
int destRow = (uint8_t)(delta[i+3]);
|
|
|
|
|
|
|
|
// std::cout << "copy " << count <<" row(s) " << srcRow << " to " << destRow << "\n";
|
|
|
|
for (int cnt = 0; cnt < count; ++cnt)
|
|
|
|
{
|
|
|
|
const char *src = &pixmap[width * (srcRow + cnt) * 4];
|
|
|
|
char *dest = &output[width * (destRow + cnt) * 4];
|
|
|
|
for (size_t j = 0; j < width * 4; ++j)
|
|
|
|
*dest++ = *src++;
|
|
|
|
}
|
|
|
|
i += 4;
|
2017-09-28 03:45:46 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 'd': // new run
|
2017-09-16 11:32:20 -05:00
|
|
|
{
|
2017-09-28 03:45:46 -05:00
|
|
|
int destRow = (uint8_t)(delta[i+1]);
|
|
|
|
int destCol = (uint8_t)(delta[i+2]);
|
|
|
|
size_t length = (uint8_t)(delta[i+3]);
|
|
|
|
i += 4;
|
|
|
|
|
2017-10-23 14:59:10 -05:00
|
|
|
// std::cout << "new " << length << " at " << destCol << ", " << destRow << "\n";
|
2020-01-20 10:45:53 -06:00
|
|
|
LOK_ASSERT(length <= width - destCol);
|
2017-09-28 03:45:46 -05:00
|
|
|
|
|
|
|
char *dest = &output[width * destRow * 4 + destCol * 4];
|
|
|
|
for (size_t j = 0; j < length * 4 && i < delta.size(); ++j)
|
|
|
|
*dest++ = delta[i++];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
std::cout << "Unknown delta code " << delta[i] << "\n";
|
2020-01-20 10:45:53 -06:00
|
|
|
LOK_ASSERT(false);
|
2017-09-28 03:45:46 -05:00
|
|
|
break;
|
2017-09-16 11:32:20 -05:00
|
|
|
}
|
|
|
|
}
|
2020-01-20 10:45:53 -06:00
|
|
|
LOK_ASSERT_EQUAL(delta.size(), i);
|
2017-09-16 11:32:20 -05:00
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeltaTests::assertEqual(const std::vector<char> &a,
|
2017-09-28 03:45:46 -05:00
|
|
|
const std::vector<char> &b,
|
|
|
|
int width, int /* height */)
|
2017-09-16 11:32:20 -05:00
|
|
|
{
|
2020-01-20 10:45:53 -06:00
|
|
|
LOK_ASSERT_EQUAL(a.size(), b.size());
|
2017-09-16 11:32:20 -05:00
|
|
|
for (size_t i = 0; i < a.size(); ++i)
|
|
|
|
{
|
|
|
|
if (a[i] != b[i])
|
|
|
|
{
|
2017-09-28 03:45:46 -05:00
|
|
|
std::cout << "Differences starting at byte " << i << " "
|
|
|
|
<< (i/4 % width) << ", " << (i / (width * 4)) << ":\n";
|
2017-09-16 11:32:20 -05:00
|
|
|
size_t len;
|
2017-09-28 03:45:46 -05:00
|
|
|
for (len = 0; (a[i+len] != b[i+len] || len < 8) && i + len < a.size(); ++len)
|
2017-09-16 11:32:20 -05:00
|
|
|
{
|
2017-09-28 03:45:46 -05:00
|
|
|
std::cout << std::hex << (int)((unsigned char)a[i+len]) << " != ";
|
|
|
|
std::cout << std::hex << (int)((unsigned char)b[i+len]) << " ";
|
2017-09-16 11:32:20 -05:00
|
|
|
if (len > 0 && (len % 16 == 0))
|
|
|
|
std::cout<< "\n";
|
|
|
|
}
|
|
|
|
std::cout << " size " << len << "\n";
|
2020-01-20 10:45:53 -06:00
|
|
|
LOK_ASSERT(false);
|
2017-09-16 11:32:20 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeltaTests::testDeltaSequence()
|
|
|
|
{
|
|
|
|
DeltaGenerator gen;
|
|
|
|
|
|
|
|
png_uint_32 height, width, rowBytes;
|
|
|
|
const TileWireId textWid = 1;
|
|
|
|
std::vector<char> text =
|
2018-04-29 19:14:33 -05:00
|
|
|
DeltaTests::loadPng(TDOC "/delta-text.png",
|
2017-09-16 11:32:20 -05:00
|
|
|
height, width, rowBytes);
|
2020-01-20 10:45:53 -06:00
|
|
|
LOK_ASSERT(height == 256 && width == 256 && rowBytes == 256*4);
|
|
|
|
LOK_ASSERT_EQUAL(size_t(256 * 256 * 4), text.size());
|
2017-09-16 11:32:20 -05:00
|
|
|
|
|
|
|
const TileWireId text2Wid = 2;
|
|
|
|
std::vector<char> text2 =
|
2018-04-29 19:14:33 -05:00
|
|
|
DeltaTests::loadPng(TDOC "/delta-text2.png",
|
2017-09-16 11:32:20 -05:00
|
|
|
height, width, rowBytes);
|
2020-01-20 10:45:53 -06:00
|
|
|
LOK_ASSERT(height == 256 && width == 256 && rowBytes == 256*4);
|
|
|
|
LOK_ASSERT_EQUAL(size_t(256 * 256 * 4), text2.size());
|
2017-09-16 11:32:20 -05:00
|
|
|
|
|
|
|
std::vector<char> delta;
|
|
|
|
// Stash it in the cache
|
2020-01-20 10:45:53 -06:00
|
|
|
LOK_ASSERT(gen.createDelta(
|
2017-09-16 11:32:20 -05:00
|
|
|
reinterpret_cast<unsigned char *>(&text[0]),
|
|
|
|
0, 0, width, height, width, height,
|
|
|
|
delta, textWid, 0) == false);
|
2020-01-20 10:45:53 -06:00
|
|
|
LOK_ASSERT(delta.size() == 0);
|
2017-09-16 11:32:20 -05:00
|
|
|
|
|
|
|
// Build a delta between text2 & textWid
|
2020-01-20 10:45:53 -06:00
|
|
|
LOK_ASSERT(gen.createDelta(
|
2017-09-16 11:32:20 -05:00
|
|
|
reinterpret_cast<unsigned char *>(&text2[0]),
|
|
|
|
0, 0, width, height, width, height,
|
|
|
|
delta, text2Wid, textWid) == true);
|
2020-01-20 10:45:53 -06:00
|
|
|
LOK_ASSERT(delta.size() > 0);
|
2017-09-16 11:32:20 -05:00
|
|
|
|
|
|
|
// Apply it to move to the second frame
|
|
|
|
std::vector<char> reText2 = applyDelta(text, width, height, delta);
|
2017-09-28 03:45:46 -05:00
|
|
|
assertEqual(reText2, text2, width, height);
|
2017-09-16 11:32:20 -05:00
|
|
|
|
|
|
|
// Build a delta between text & text2Wid
|
|
|
|
std::vector<char> two2one;
|
2020-01-20 10:45:53 -06:00
|
|
|
LOK_ASSERT(gen.createDelta(
|
2017-09-16 11:32:20 -05:00
|
|
|
reinterpret_cast<unsigned char *>(&text[0]),
|
|
|
|
0, 0, width, height, width, height,
|
|
|
|
two2one, textWid, text2Wid) == true);
|
2020-01-20 10:45:53 -06:00
|
|
|
LOK_ASSERT(two2one.size() > 0);
|
2017-09-16 11:32:20 -05:00
|
|
|
|
|
|
|
// Apply it to get back to where we started
|
|
|
|
std::vector<char> reText = applyDelta(text2, width, height, two2one);
|
2017-09-28 03:45:46 -05:00
|
|
|
assertEqual(reText, text, width, height);
|
2017-09-16 11:32:20 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void DeltaTests::testRandomDeltas()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
CPPUNIT_TEST_SUITE_REGISTRATION(DeltaTests);
|
|
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|