// Copyright (C) 2004 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #include <sstream> #include <string> #include <ctime> #include <cstdlib> #include <dlib/sliding_buffer.h> #include <dlib/lz77_buffer.h> #include "tester.h" namespace { using namespace test; using namespace std; using namespace dlib; logger dlog("test.lz77_buffer"); template < typename buf > void lz77_buffer_kernel_test ( ) /*! requires - buf is an implementation of lz77_buffer/lz77_buffer_kernel_abstract.h ensures - runs tests on buf for compliance with the specs !*/ { typedef dlib::sliding_buffer<unsigned char>::kernel_1a sbuf; buf test(8,20); srand(static_cast<unsigned int>(time(0))); DLIB_TEST(test.get_lookahead_buffer_size() == 0); DLIB_TEST(test.get_history_buffer_size() == 0); DLIB_TEST_MSG(test.get_history_buffer_limit() == 256-20,test.get_history_buffer_limit()); DLIB_TEST(test.get_lookahead_buffer_limit() == 20); for (int g = 0; g < 2; ++g) { test.clear(); for (int i = 0; i < 1000; ++i) { test.add('a'); } DLIB_TEST(test.get_lookahead_buffer_size() == 20); test.shift_buffers(5); DLIB_TEST(test.get_lookahead_buffer_size() == 15); unsigned long index, length, temp; temp = test.get_lookahead_buffer_size(); test.find_match(index,length,5); DLIB_TEST_MSG(length <= temp, "length: " << length << "\ntemp: " << temp); DLIB_TEST(test.get_lookahead_buffer_size() <= 15); } for (int g = 0; g < 2; ++g) { test.clear(); DLIB_TEST(test.get_lookahead_buffer_size() == 0); DLIB_TEST(test.get_history_buffer_size() == 0); DLIB_TEST(test.get_history_buffer_limit() == 256-20); DLIB_TEST(test.get_lookahead_buffer_limit() == 20); unsigned long a,b, temp = test.get_lookahead_buffer_size(); test.find_match(a,b,0); DLIB_TEST(b <= temp); DLIB_TEST(b == 0); test.find_match(a,b,5); DLIB_TEST(b == 0); DLIB_TEST(test.get_lookahead_buffer_size() == 0); DLIB_TEST(test.get_history_buffer_size() == 0); DLIB_TEST(test.get_history_buffer_limit() == 256-20); DLIB_TEST(test.get_lookahead_buffer_limit() == 20); ostringstream sout; sout << "DLIB_TEST_MSG(test.get_lookahead_buffer_size() == 0,);\n"; sout << "DLIB_TEST_MSG(test.get_history_buffer_size() == 0,);\n"; sout << "DLIB_TEST_MSG(test.get_history_buffer_limit() == 256-20,);\n"; sout << "DLIB_TEST_MSG(test.get_lookahead_buffer_limit() == 20,);\n"; sout << "DLIB_TEST_MSG(test.get_lookahead_buffer_size() == 0,);\n"; sout << "DLIB_TEST_MSG(test.get_history_buffer_size() == 0,);\n"; sout << "DLIB_TEST_MSG(test.get_history_buffer_limit() == 256-20,);\n"; sout << "DLIB_TEST_MSG(test.get_lookahead_buffer_limit() == 20,);\n"; istringstream sin(sout.str()); sout.str(""); sout.clear(); unsigned char ch; sbuf sbuffer; sbuffer.set_size(8); ch = sin.get(); sbuffer[0] = ch; sbuffer.rotate_left(1); test.add(ch); DLIB_TEST(test.lookahead_buffer(test.get_lookahead_buffer_size()-1) == ch); DLIB_TEST(test.get_lookahead_buffer_size() == 1); DLIB_TEST(test.get_history_buffer_size() == 0); DLIB_TEST(test.get_lookahead_buffer_limit() == 20); ch = sin.get(); sbuffer[0] = ch; sbuffer.rotate_left(1); test.add(ch); DLIB_TEST(test.lookahead_buffer(test.get_lookahead_buffer_size()-1) == ch); DLIB_TEST(test.get_lookahead_buffer_size() == 2); DLIB_TEST(test.get_history_buffer_size() == 0); DLIB_TEST(test.get_lookahead_buffer_limit() == 20); ch = sin.get(); sbuffer[0] = ch; sbuffer.rotate_left(1); test.add(ch); DLIB_TEST(test.lookahead_buffer(test.get_lookahead_buffer_size()-1) == ch); DLIB_TEST(test.get_lookahead_buffer_size() == 3); DLIB_TEST(test.get_history_buffer_size() == 0); // add 17 chars to test so that the lookahead buffer will be full for (int i = 0; i < 17; ++i) { ch = sin.get(); sbuffer[0] = ch; sbuffer.rotate_left(1); test.add(ch); DLIB_TEST(test.lookahead_buffer(test.get_lookahead_buffer_size()-1) == ch); } DLIB_TEST(test.get_lookahead_buffer_size() == 20); DLIB_TEST(test.get_history_buffer_size() == 0); DLIB_TEST(test.lookahead_buffer(0) == sbuffer[20]); ch = sin.get(); sbuffer[0] = ch; sbuffer.rotate_left(1); test.add(ch); DLIB_TEST(test.lookahead_buffer(test.get_lookahead_buffer_size()-1) == ch); DLIB_TEST(test.get_lookahead_buffer_size() == 20); DLIB_TEST(test.get_history_buffer_size() == 1); // add the above text to test and make sure it gives the correct results ch = sin.get(); while (sin) { sbuffer[0] = ch; sbuffer.rotate_left(1); test.add(ch); DLIB_TEST(test.lookahead_buffer(test.get_lookahead_buffer_size()-1) == ch); DLIB_TEST(test.history_buffer(0) == sbuffer[21]); DLIB_TEST(test.history_buffer(1) == sbuffer[22]); ch = sin.get(); } // make sure the contents of lookahead_buffer and history_buffer // match what is in sbuffer sbuffer.rotate_right(1); for (unsigned int i = 0; i < test.get_history_buffer_size(); ++i) { DLIB_TEST(sbuffer[test.get_lookahead_buffer_limit()+i] == test.history_buffer(i)); } for (unsigned int i = 0; i < test.get_lookahead_buffer_size(); ++i) { DLIB_TEST(sbuffer[test.get_lookahead_buffer_limit()-1-i] == test.lookahead_buffer(i)); } sbuffer.rotate_left(1); sbuffer.rotate_right(1); // do this because we never put anything in sbuffer[0] unsigned long match_index, match_length; unsigned long ltemp = test.get_lookahead_buffer_size(); test.find_match(match_index,match_length,0); DLIB_TEST(match_length <= ltemp); // verify the match with sbuffer for (unsigned int i = 0; i < match_length; ++i) { DLIB_TEST_MSG(sbuffer[19-i] == sbuffer[match_index+20-i],i); } sin.str(""); sin.clear(); } // for (int g = 0; g < 2; ++g) for (int g = 0; g < 8; ++g) { test.clear(); DLIB_TEST(test.get_lookahead_buffer_size() == 0); DLIB_TEST(test.get_history_buffer_size() == 0); DLIB_TEST(test.get_history_buffer_limit() == 256-20); DLIB_TEST(test.get_lookahead_buffer_limit() == 20); sbuf sbuffer; sbuffer.set_size(8); ostringstream sout; sout << "DLIB_TEST_MSG(test.get_lookahead_buffer_size() == 0,);\n"; sout << "DLIB_TEST_MSG(test.get_history_buffer_size() == 0,);\n"; sout << "DLIB_TEST_MSG(test.get_history_buffer_limit() == 256-20,);\n"; sout << "DLIB_TEST_MSG(test.get_lookahead_buffer_limit() == 20,);\n"; sout << "DLIB_TEST_MSG(test.get_lookahead_buffer_size() == 0,);\n"; sout << "DLIB_TEST_MSG(test.get_history_buffer_limit() == 256-20,);\n"; sout << "DLIB_TEST_MSG(test.get_lookahead_buffer_limit() == 20,);\n"; sout << "DLIB_TEST_MSG(test.get_history_buffer_limit() == 256-20,);\n"; sout << "DLIB_TEST_MSG(test.get_lookahead_buffer_size() == 0,);\n"; sout << "DLIB_TEST_MSG(test.get_history_buffer_limit() == 256-20,);\n"; sout << "DLIB_TEST_MSG(test.get_history_buffer_limit() == 256-20,);\n"; istringstream sin(sout.str()); unsigned char ch; for (int i = 0; i < 100; ++i) { ch = sin.get(); sbuffer[0] = ch; sbuffer.rotate_left(1); test.add(ch); } // make sure the contents of lookahead_buffer and history_buffer // match what is in sbuffer sbuffer.rotate_right(1); for (unsigned int i = 0; i < test.get_history_buffer_size(); ++i) { DLIB_TEST(sbuffer[test.get_lookahead_buffer_limit()+i] == test.history_buffer(i)); } for (unsigned int i = 0; i < test.get_lookahead_buffer_size(); ++i) { DLIB_TEST(sbuffer[test.get_lookahead_buffer_limit()-1-i] == test.lookahead_buffer(i)); } sbuffer.rotate_left(1); unsigned long match_index, match_length; unsigned long ltemp = test.get_lookahead_buffer_size(); test.find_match(match_index,match_length,0); DLIB_TEST(match_length <= ltemp); DLIB_TEST(test.get_lookahead_buffer_size() == 20-match_length); sbuffer.rotate_right(1); // do this because we never put anything in sbuffer[0] // verify the match with sbuffer for (unsigned int i = 0; i < match_length; ++i) { DLIB_TEST(sbuffer[i+20-match_length] == sbuffer[i+1+match_index+20-match_length]); } sbuffer.rotate_left(1); // free up sbuffer[0] for new data for (int i = 0; i < 7+g*2; ++i) { ch = sin.get(); sbuffer[0] = ch; sbuffer.rotate_left(1); test.add(ch); } ch = '?'; sbuffer[0] = ch; sbuffer.rotate_left(1); test.add(ch); ch = 'a'; sbuffer[0] = ch; sbuffer.rotate_left(1); test.add(ch); ch = 'v'; sbuffer[0] = ch; sbuffer.rotate_left(1); test.add(ch); ch = 'i'; sbuffer[0] = ch; sbuffer.rotate_left(1); test.add(ch); ch = 's'; sbuffer[0] = ch; sbuffer.rotate_left(1); test.add(ch); // adjust sbuffer due to the last call to test.find_match() // but only if we haven't already added enough (20 or more) chars // to fill the lookahead buffer already. if (match_length > static_cast<unsigned int>(12+g*2)) sbuffer.rotate_left(match_length-(12+g*2)); // make sure the contents of lookahead_buffer and history_buffer // match what is in sbuffer sbuffer.rotate_right(1); for (unsigned int i = 0; i < test.get_history_buffer_size(); ++i) { DLIB_TEST(sbuffer[test.get_lookahead_buffer_limit()+i] == test.history_buffer(i)); } for (unsigned int i = 0; i < test.get_lookahead_buffer_size(); ++i) { DLIB_TEST(sbuffer[test.get_lookahead_buffer_limit()-1-i] == test.lookahead_buffer(i)); } sbuffer.rotate_left(1); test.find_match(match_index,match_length,10+g); if (match_length > 0) DLIB_TEST(match_length >= static_cast<unsigned int>(10+g) ); sbuffer.rotate_right(1); // do this because we never put anything in sbuffer[0] // verify the match with sbuffer for (unsigned int i = 0; i < match_length; ++i) { DLIB_TEST(sbuffer[i+20-match_length] == sbuffer[i+1+match_index+20-match_length]); } sbuffer.rotate_left(1); // free up sbuffer[0] for new data } // for (int g = 0; g < 8; ++g) srand(static_cast<unsigned int>(time(0))); for (int g = 0; g < 200; ++g) { test.clear(); DLIB_TEST(test.get_lookahead_buffer_size() == 0); DLIB_TEST(test.get_history_buffer_size() == 0); DLIB_TEST(test.get_history_buffer_limit() == 256-20); DLIB_TEST(test.get_lookahead_buffer_limit() == 20); sbuf sbuffer; sbuffer.set_size(8); ostringstream sout; int l = ::rand()%500; for (int i = 0; i < l; ++i) { char temp = static_cast<char>(::rand()%256); sout << temp; } istringstream sin(sout.str()); unsigned char ch; for (int i = 0; i < l; ++i) { ch = sin.get(); sbuffer[0] = ch; sbuffer.rotate_left(1); test.add(ch); } // make sure the contents of lookahead_buffer and history_buffer // match what is in sbuffer sbuffer.rotate_right(1); // adjust so that sbuffer[19] is the same as lookahead_buffer[0] if (test.get_lookahead_buffer_size() < 20) sbuffer.rotate_left(20-test.get_lookahead_buffer_size()); for (unsigned int i = 0; i < test.get_history_buffer_size(); ++i) { DLIB_TEST(sbuffer[test.get_lookahead_buffer_limit()+i] == test.history_buffer(i)); } for (unsigned int i = 0; i < test.get_lookahead_buffer_size(); ++i) { DLIB_TEST(sbuffer[test.get_lookahead_buffer_limit()-1-i] == test.lookahead_buffer(i)); } sbuffer.rotate_left(1); unsigned long match_index, match_length; unsigned long lookahead_size_before = test.get_lookahead_buffer_size(); test.find_match(match_index,match_length,0); DLIB_TEST(match_length <= lookahead_size_before); DLIB_TEST(test.get_lookahead_buffer_size() == lookahead_size_before-match_length); sbuffer.rotate_right(1); // do this because we never put anything in sbuffer[0] // verify the match with sbuffer for (unsigned int i = 0; i < match_length; ++i) { DLIB_TEST_MSG(sbuffer[19-i] == sbuffer[match_index+20-i],i); } sbuffer.rotate_left(1); // free up sbuffer[0] for new data } // for (int g = 0; g < 200; ++g) srand(static_cast<unsigned int>(time(0))); for (int g = 0; g < 300; ++g) { test.clear(); DLIB_TEST(test.get_lookahead_buffer_size() == 0); DLIB_TEST(test.get_history_buffer_size() == 0); DLIB_TEST(test.get_history_buffer_limit() == 256-20); DLIB_TEST(test.get_lookahead_buffer_limit() == 20); sbuf sbuffer; sbuffer.set_size(8); ostringstream sout; int l = ::rand()%500; for (int i = 0; i < l; ++i) { char temp = static_cast<char>(::rand()%20); sout << temp; sout << temp; sout << temp; sout << temp; sout << temp; sout << temp; } istringstream sin(sout.str()); unsigned char ch; for (int i = 0; i < l; ++i) { ch = sin.get(); sbuffer[0] = ch; sbuffer.rotate_left(1); test.add(ch); } // make sure the contents of lookahead_buffer and history_buffer // match what is in sbuffer sbuffer.rotate_right(1); // adjust so that sbuffer[19] is the same as lookahead_buffer[0] if (test.get_lookahead_buffer_size() < 20) sbuffer.rotate_left(20-test.get_lookahead_buffer_size()); for (unsigned int i = 0; i < test.get_history_buffer_size(); ++i) { DLIB_TEST(sbuffer[test.get_lookahead_buffer_limit()+i] == test.history_buffer(i)); } for (unsigned int i = 0; i < test.get_lookahead_buffer_size(); ++i) { DLIB_TEST(sbuffer[test.get_lookahead_buffer_limit()-1-i] == test.lookahead_buffer(i)); } sbuffer.rotate_left(1); unsigned long match_index = 0, match_length = 0; unsigned long lookahead_size_before = test.get_lookahead_buffer_size(); unsigned long history_size_before = test.get_history_buffer_size(); test.find_match(match_index,match_length,2); if (match_length != 0) { DLIB_TEST_MSG(match_index < history_size_before, "match_index: " << match_index << "\nhistory_size_before: " << history_size_before); } DLIB_TEST(test.get_lookahead_buffer_size() == lookahead_size_before-match_length); sbuffer.rotate_right(1); // do this because we never put anything in sbuffer[0] // verify the match with sbuffer for (unsigned int i = 0; i < match_length; ++i) { DLIB_TEST_MSG(sbuffer[19-i] == sbuffer[match_index+20-i],i); } sbuffer.rotate_left(1); // free up sbuffer[0] for new data } // for (int g = 0; g < 300; ++g) } class lz77_buffer_tester : public tester { public: lz77_buffer_tester ( ) : tester ("test_lz77_buffer", "Runs tests on the lz77_buffer component.") {} void perform_test ( ) { dlog << LINFO << "testing kernel_1a"; lz77_buffer_kernel_test<lz77_buffer::kernel_1a> (); dlog << LINFO << "testing kernel_1a_c"; lz77_buffer_kernel_test<lz77_buffer::kernel_1a_c>(); dlog << LINFO << "testing kernel_2a"; lz77_buffer_kernel_test<lz77_buffer::kernel_2a> (); dlog << LINFO << "testing kernel_2a_c"; lz77_buffer_kernel_test<lz77_buffer::kernel_2a_c>(); } } a; }