mirror of
https://github.com/pdewacht/brlaser
synced 2025-07-20 15:49:46 +02:00
Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
fa26a6149a | |||
2e37d9d62a | |||
77ce307fdb | |||
7bfe0d2846 | |||
5159844b03 | |||
bb1ba17b4f | |||
cd0e4102b4 | |||
66ea095ede |
9
.gitignore
vendored
9
.gitignore
vendored
@ -11,11 +11,16 @@
|
|||||||
/stamp-*
|
/stamp-*
|
||||||
.deps/
|
.deps/
|
||||||
.dirstamp
|
.dirstamp
|
||||||
|
*.log
|
||||||
|
*.trs
|
||||||
|
|
||||||
#
|
#
|
||||||
# Binaries
|
# Binaries
|
||||||
#
|
#
|
||||||
/rastertobrlaser
|
/src/rastertobrlaser
|
||||||
/brdecode
|
/src/brdecode
|
||||||
|
/test/test_lest
|
||||||
|
/test/test_line
|
||||||
|
/test/test_block
|
||||||
/brlaser.drv
|
/brlaser.drv
|
||||||
*.o
|
*.o
|
||||||
|
6
ChangeLog
Normal file
6
ChangeLog
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
brlaser v2 (2014-06-29)
|
||||||
|
Suppport compilation with GCC 4.6.
|
||||||
|
Add a basic test suite.
|
||||||
|
|
||||||
|
brlaser v1 (2013-12-30)
|
||||||
|
Initial release.
|
40
Makefile.am
40
Makefile.am
@ -1,24 +1,50 @@
|
|||||||
ACLOCAL_AMFLAGS = -I m4
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
|
AM_CXXFLAGS = $(CUPS_CFLAGS)
|
||||||
|
TESTS = $(check_PROGRAMS)
|
||||||
|
|
||||||
filter_PROGRAMS = rastertobrlaser
|
|
||||||
filterdir = $(CUPS_SERVERBIN)/filter
|
dist_doc_DATA = README.md
|
||||||
|
|
||||||
drv_DATA = brlaser.drv
|
drv_DATA = brlaser.drv
|
||||||
drvdir = $(CUPS_DATADIR)/drv
|
drvdir = $(CUPS_DATADIR)/drv
|
||||||
|
|
||||||
noinst_PROGRAMS = brdecode
|
filter_PROGRAMS = src/rastertobrlaser
|
||||||
|
filterdir = $(CUPS_SERVERBIN)/filter
|
||||||
|
|
||||||
|
noinst_PROGRAMS = src/brdecode
|
||||||
|
|
||||||
|
check_PROGRAMS = \
|
||||||
|
test/test_lest \
|
||||||
|
test/test_line \
|
||||||
|
test/test_block
|
||||||
|
|
||||||
|
|
||||||
rastertobrlaser_SOURCES = \
|
src_rastertobrlaser_SOURCES = \
|
||||||
src/main.cc \
|
src/main.cc \
|
||||||
src/debug.h \
|
src/debug.h \
|
||||||
src/debug.cc \
|
src/debug.cc \
|
||||||
src/job.h \
|
src/job.h \
|
||||||
src/job.cc \
|
src/job.cc \
|
||||||
|
src/block.h \
|
||||||
src/line.h \
|
src/line.h \
|
||||||
src/line.cc
|
src/line.cc
|
||||||
rastertobrlaser_CPPFLAGS = $(CUPS_CFLAGS)
|
src_rastertobrlaser_LDADD = $(CUPS_LIBS)
|
||||||
rastertobrlaser_LDADD = $(CUPS_LIBS)
|
|
||||||
|
|
||||||
brdecode_SOURCES = \
|
src_brdecode_SOURCES = \
|
||||||
src/brdecode.cc
|
src/brdecode.cc
|
||||||
|
|
||||||
|
test_test_lest_SOURCES = \
|
||||||
|
test/test_lest.cc \
|
||||||
|
test/lest.h
|
||||||
|
|
||||||
|
test_test_line_SOURCES = \
|
||||||
|
test/test_line.cc \
|
||||||
|
src/line.h \
|
||||||
|
src/line.cc \
|
||||||
|
test/lest.h
|
||||||
|
|
||||||
|
test_test_block_SOURCES = \
|
||||||
|
test/test_block.cc \
|
||||||
|
src/block.h \
|
||||||
|
test/tempfile.h \
|
||||||
|
test/lest.h
|
||||||
|
@ -17,7 +17,7 @@ Requirements
|
|||||||
------------
|
------------
|
||||||
|
|
||||||
* CUPS: tested with version 1.6.
|
* CUPS: tested with version 1.6.
|
||||||
* A C++11 compiler. A recent version of GCC or Clang will work.
|
* A C++11 compiler: GCC 4.6 or later, or a recent version of Clang.
|
||||||
|
|
||||||
Copyright
|
Copyright
|
||||||
---------
|
---------
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
# along with brlaser. If not, see <http:#www.gnu.org/licenses/>.
|
# along with brlaser. If not, see <http:#www.gnu.org/licenses/>.
|
||||||
|
|
||||||
AC_PREREQ(2.68)
|
AC_PREREQ(2.68)
|
||||||
AC_INIT([brlaser], [1], [pdewacht@gmail.com], [brlaser],
|
AC_INIT([brlaser], [2], [pdewacht@gmail.com], [brlaser],
|
||||||
[https://github.com/pdewacht/brlaser])
|
[https://github.com/pdewacht/brlaser])
|
||||||
|
|
||||||
AC_CONFIG_SRCDIR([src/line.cc])
|
AC_CONFIG_SRCDIR([src/line.cc])
|
||||||
|
63
src/block.h
Normal file
63
src/block.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
// This file is part of the brlaser printer driver.
|
||||||
|
//
|
||||||
|
// Copyright 2013 Peter De Wachter
|
||||||
|
//
|
||||||
|
// brlaser is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 2 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// brlaser is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with brlaser. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#ifndef BLOCK_H
|
||||||
|
#define BLOCK_H
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class block {
|
||||||
|
public:
|
||||||
|
block(): line_bytes_(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_line(std::vector<uint8_t> &&line) {
|
||||||
|
assert(!line.empty());
|
||||||
|
assert(line_fits(line.size()));
|
||||||
|
line_bytes_ += line.size();
|
||||||
|
lines_.push_back(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool line_fits(unsigned size) {
|
||||||
|
return lines_.size() != max_lines_per_block_
|
||||||
|
&& line_bytes_ + size < max_block_size_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void flush(FILE *f) {
|
||||||
|
if (line_bytes_) {
|
||||||
|
fprintf(f, "%dw%c%c",
|
||||||
|
line_bytes_ + 2, 0,
|
||||||
|
static_cast<int>(lines_.size()));
|
||||||
|
for (auto &line : lines_) {
|
||||||
|
fwrite(line.data(), 1, line.size(), f);
|
||||||
|
}
|
||||||
|
line_bytes_ = 0;
|
||||||
|
lines_.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const unsigned max_block_size_ = 16350;
|
||||||
|
static const unsigned max_lines_per_block_ = 128;
|
||||||
|
|
||||||
|
std::vector<std::vector<uint8_t>> lines_;
|
||||||
|
int line_bytes_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BLOCK_H
|
@ -16,6 +16,7 @@
|
|||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
@ -127,9 +128,9 @@ void read_line() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void read_block() {
|
void read_block() {
|
||||||
uint8_t count = get();
|
unsigned count = get();
|
||||||
count = count * 256 + get();
|
count = count * 256 + get();
|
||||||
for (int i = 0; i < count; ++i) {
|
for (unsigned i = 0; i < count; ++i) {
|
||||||
read_line();
|
read_line();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
46
src/job.cc
46
src/job.cc
@ -20,46 +20,8 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "line.h"
|
#include "line.h"
|
||||||
|
#include "block.h"
|
||||||
|
|
||||||
using std::vector;
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
class block {
|
|
||||||
public:
|
|
||||||
void add_line(vector<uint8_t> &&line) {
|
|
||||||
assert(!line.empty());
|
|
||||||
line_bytes_ += line.size();
|
|
||||||
lines_.push_back(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool line_fits(unsigned size) {
|
|
||||||
return lines_.size() != max_lines_per_block_
|
|
||||||
&& line_bytes_ + size < max_block_size_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void flush(FILE *f) {
|
|
||||||
if (line_bytes_) {
|
|
||||||
fprintf(f, "%dw%c%c",
|
|
||||||
line_bytes_ + 2, 0,
|
|
||||||
static_cast<int>(lines_.size()));
|
|
||||||
for (auto &line : lines_) {
|
|
||||||
fwrite(line.data(), 1, line.size(), f);
|
|
||||||
}
|
|
||||||
line_bytes_ = 0;
|
|
||||||
lines_.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const unsigned max_block_size_ = 16350;
|
|
||||||
const unsigned max_lines_per_block_ = 128;
|
|
||||||
|
|
||||||
vector<vector<uint8_t>> lines_;
|
|
||||||
int line_bytes_ = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
job::job(FILE *out, const std::string &job_name)
|
job::job(FILE *out, const std::string &job_name)
|
||||||
: out_(out),
|
: out_(out),
|
||||||
@ -123,8 +85,8 @@ void job::encode_page(const page_params &page_params,
|
|||||||
write_page_header();
|
write_page_header();
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<uint8_t> line(linesize);
|
std::vector<uint8_t> line(linesize);
|
||||||
vector<uint8_t> reference(linesize);
|
std::vector<uint8_t> reference(linesize);
|
||||||
block block;
|
block block;
|
||||||
|
|
||||||
if (!nextline(line.data())) {
|
if (!nextline(line.data())) {
|
||||||
@ -138,7 +100,7 @@ void job::encode_page(const page_params &page_params,
|
|||||||
fputs("\033*b1030m", out_);
|
fputs("\033*b1030m", out_);
|
||||||
|
|
||||||
for (int i = 1; i < lines && nextline(line.data()); ++i) {
|
for (int i = 1; i < lines && nextline(line.data()); ++i) {
|
||||||
vector<uint8_t> encoded = encode_line(line, reference);
|
std::vector<uint8_t> encoded = encode_line(line, reference);
|
||||||
if (!block.line_fits(encoded.size())) {
|
if (!block.line_fits(encoded.size())) {
|
||||||
block.flush(out_);
|
block.flush(out_);
|
||||||
}
|
}
|
||||||
|
199
test/lest.hpp
Normal file
199
test/lest.hpp
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
// Copyright 2013 by Martin Moene
|
||||||
|
//
|
||||||
|
// lest is based on ideas by Kevlin Henney, see video at
|
||||||
|
// http://skillsmatter.com/podcast/agile-testing/kevlin-henney-rethinking-unit-testing-in-c-plus-plus
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0:
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person or organization
|
||||||
|
// obtaining a copy of the software and accompanying documentation covered by
|
||||||
|
// this license (the "Software") to use, reproduce, display, distribute,
|
||||||
|
// execute, and transmit the Software, and to prepare derivative works of the
|
||||||
|
// Software, and to permit third-parties to whom the Software is furnished to
|
||||||
|
// do so, all subject to the following:
|
||||||
|
//
|
||||||
|
// The copyright notices in the Software and this entire statement, including
|
||||||
|
// the above license grant, this restriction and the following disclaimer,
|
||||||
|
// must be included in all copies of the Software, in whole or in part, and
|
||||||
|
// all derivative works of the Software, unless such copies or derivative
|
||||||
|
// works are solely in the form of machine-executable object code generated by
|
||||||
|
// a source language processor.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||||
|
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||||
|
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||||
|
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
#ifndef LEST_LEST_H_INCLUDED
|
||||||
|
#define LEST_LEST_H_INCLUDED
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
#ifndef lest_NO_SHORT_ASSERTION_NAMES
|
||||||
|
# define EXPECT lest_EXPECT
|
||||||
|
# define EXPECT_THROWS lest_EXPECT_THROWS
|
||||||
|
# define EXPECT_THROWS_AS lest_EXPECT_THROWS_AS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define lest_EXPECT( expr ) \
|
||||||
|
try \
|
||||||
|
{ \
|
||||||
|
if ( ! (expr) ) \
|
||||||
|
throw lest::failure{ lest_LOCATION, #expr }; \
|
||||||
|
} \
|
||||||
|
catch( lest::failure const & ) \
|
||||||
|
{ \
|
||||||
|
throw ; \
|
||||||
|
} \
|
||||||
|
catch( std::exception const & e ) \
|
||||||
|
{ \
|
||||||
|
throw lest::unexpected{ lest_LOCATION, #expr, lest::with_message( e.what() ) }; \
|
||||||
|
} \
|
||||||
|
catch(...) \
|
||||||
|
{ \
|
||||||
|
throw lest::unexpected{ lest_LOCATION, #expr, "of unknown type" }; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define lest_EXPECT_THROWS( expr ) \
|
||||||
|
for (;;) \
|
||||||
|
{ \
|
||||||
|
try { lest::serum( expr ); } catch (...) { break; } \
|
||||||
|
throw lest::expected{ lest_LOCATION, #expr }; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define lest_EXPECT_THROWS_AS( expr, excpt ) \
|
||||||
|
for (;;) \
|
||||||
|
{ \
|
||||||
|
try { lest::serum( expr ); } catch ( excpt & ) { break; } catch (...) {} \
|
||||||
|
throw lest::expected{ lest_LOCATION, #expr, lest::of_type( #excpt ) }; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define lest_LOCATION lest::location{__FILE__, __LINE__}
|
||||||
|
|
||||||
|
namespace lest {
|
||||||
|
|
||||||
|
struct test
|
||||||
|
{
|
||||||
|
const std::string name;
|
||||||
|
const std::function<void()> behaviour;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct location
|
||||||
|
{
|
||||||
|
const std::string file;
|
||||||
|
const int line;
|
||||||
|
|
||||||
|
location( std::string file, int line )
|
||||||
|
: file{ file }, line{ line } {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct comment
|
||||||
|
{
|
||||||
|
const std::string text;
|
||||||
|
|
||||||
|
comment( std::string text ) : text{ text } {}
|
||||||
|
explicit operator bool() { return ! text.empty(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct message : std::runtime_error
|
||||||
|
{
|
||||||
|
const std::string kind;
|
||||||
|
const location where;
|
||||||
|
const comment note;
|
||||||
|
|
||||||
|
~message() throw() {} // GCC 4.6
|
||||||
|
|
||||||
|
message( std::string kind, location where, std::string expr, std::string note = "" )
|
||||||
|
: std::runtime_error{ expr }, kind{ kind }, where{ where }, note{ note } {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct failure : message
|
||||||
|
{
|
||||||
|
failure( location where, std::string expr )
|
||||||
|
: message{ "failed", where, expr } {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct expected : message
|
||||||
|
{
|
||||||
|
expected( location where, std::string expr, std::string excpt = "" )
|
||||||
|
: message{ "failed: didn't get exception", where, expr, excpt } {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct unexpected : message
|
||||||
|
{
|
||||||
|
unexpected( location where, std::string expr, std::string note )
|
||||||
|
: message{ "failed: got unexpected exception", where, expr, note } {}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool serum( bool verum ) { return verum; }
|
||||||
|
|
||||||
|
inline std::string with_message( std::string text )
|
||||||
|
{
|
||||||
|
return "with message \"" + text + "\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string of_type( std::string text )
|
||||||
|
{
|
||||||
|
return "of type " + text;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string pluralise( int n, std::string text )
|
||||||
|
{
|
||||||
|
return n == 1 ? text : text + "s";
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::ostream & operator<<( std::ostream & os, comment note )
|
||||||
|
{
|
||||||
|
return os << (note ? " " + note.text : "" );
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::ostream & operator<<( std::ostream & os, location where )
|
||||||
|
{
|
||||||
|
#ifdef __GNUG__
|
||||||
|
return os << where.file << ":" << where.line;
|
||||||
|
#else
|
||||||
|
return os << where.file << "(" << where.line << ")";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void report( std::ostream & os, message const & e, std::string test )
|
||||||
|
{
|
||||||
|
os << e.where << ": " << e.kind << e.note << ": " << test << ": " << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N>
|
||||||
|
int run( test const (&specification)[N], std::ostream & os = std::cout )
|
||||||
|
{
|
||||||
|
int failures = 0;
|
||||||
|
|
||||||
|
for ( auto & testing : specification )
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
testing.behaviour();
|
||||||
|
}
|
||||||
|
catch( message const & e )
|
||||||
|
{
|
||||||
|
++failures;
|
||||||
|
report( os, e, testing.name );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( failures > 0 )
|
||||||
|
{
|
||||||
|
os << failures << " out of " << N << " " << pluralise(N, "test") << " failed." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return failures;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace lest
|
||||||
|
|
||||||
|
#endif // LEST_LEST_H_INCLUDED
|
54
test/tempfile.h
Normal file
54
test/tempfile.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
// This file is part of the brlaser printer driver.
|
||||||
|
//
|
||||||
|
// Copyright 2014 Peter De Wachter
|
||||||
|
//
|
||||||
|
// brlaser is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 2 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// brlaser is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with brlaser. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#ifndef TEMPFILE_H
|
||||||
|
#define TEMPFILE_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class tempfile {
|
||||||
|
public:
|
||||||
|
explicit tempfile()
|
||||||
|
: ptr_(0),
|
||||||
|
size_(0),
|
||||||
|
file_(open_memstream(&ptr_, &size_)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
~tempfile() {
|
||||||
|
fclose(file_);
|
||||||
|
free(ptr_);
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *file() {
|
||||||
|
return file_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> data() {
|
||||||
|
if (fflush(file_))
|
||||||
|
return std::vector<uint8_t>();
|
||||||
|
return std::vector<uint8_t>(ptr_, ptr_ + size_);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
char *ptr_;
|
||||||
|
size_t size_;
|
||||||
|
FILE *file_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TEMPFILE_H
|
75
test/test_block.cc
Normal file
75
test/test_block.cc
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
// This file is part of the brlaser printer driver.
|
||||||
|
//
|
||||||
|
// Copyright 2014 Peter De Wachter
|
||||||
|
//
|
||||||
|
// brlaser is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 2 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// brlaser is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with brlaser. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include "lest.hpp"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <vector>
|
||||||
|
#include "tempfile.h"
|
||||||
|
#include "src/block.h"
|
||||||
|
|
||||||
|
typedef std::vector<uint8_t> vec;
|
||||||
|
|
||||||
|
const lest::test specification[] = {
|
||||||
|
"Block line limit",
|
||||||
|
[] {
|
||||||
|
block b;
|
||||||
|
for (int i = 0; i < 128; ++i) {
|
||||||
|
EXPECT(b.line_fits(1));
|
||||||
|
b.add_line(vec(1));
|
||||||
|
}
|
||||||
|
EXPECT(!b.line_fits(1));
|
||||||
|
},
|
||||||
|
|
||||||
|
"Block size limit",
|
||||||
|
[] {
|
||||||
|
block b;
|
||||||
|
for (int i = 0; i < 16; ++i) {
|
||||||
|
EXPECT(b.line_fits(1000));
|
||||||
|
b.add_line(vec(1000));
|
||||||
|
}
|
||||||
|
EXPECT(!b.line_fits(400));
|
||||||
|
},
|
||||||
|
|
||||||
|
"Flush",
|
||||||
|
[] {
|
||||||
|
block b;
|
||||||
|
{
|
||||||
|
tempfile f;
|
||||||
|
b.flush(f.file());
|
||||||
|
EXPECT(f.data().empty());
|
||||||
|
}
|
||||||
|
for (uint8_t n = 0; n < 10; n += 2) {
|
||||||
|
vec line = {n, static_cast<uint8_t>(n+1)};
|
||||||
|
EXPECT(b.line_fits(line.size()));
|
||||||
|
b.add_line(std::move(line));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
tempfile f;
|
||||||
|
b.flush(f.file());
|
||||||
|
EXPECT(( f.data() == vec{'1','2','w',0,5,0,1,2,3,4,5,6,7,8,9} ));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
tempfile f;
|
||||||
|
b.flush(f.file());
|
||||||
|
EXPECT(f.data().empty());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
return lest::run(specification);
|
||||||
|
}
|
291
test/test_lest.cc
Normal file
291
test/test_lest.cc
Normal file
@ -0,0 +1,291 @@
|
|||||||
|
// Copyright 2013 by Martin Moene
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0:
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person or organization
|
||||||
|
// obtaining a copy of the software and accompanying documentation covered by
|
||||||
|
// this license (the "Software") to use, reproduce, display, distribute,
|
||||||
|
// execute, and transmit the Software, and to prepare derivative works of the
|
||||||
|
// Software, and to permit third-parties to whom the Software is furnished to
|
||||||
|
// do so, all subject to the following:
|
||||||
|
//
|
||||||
|
// The copyright notices in the Software and this entire statement, including
|
||||||
|
// the above license grant, this restriction and the following disclaimer,
|
||||||
|
// must be included in all copies of the Software, in whole or in part, and
|
||||||
|
// all derivative works of the Software, unless such copies or derivative
|
||||||
|
// works are solely in the form of machine-executable object code generated by
|
||||||
|
// a source language processor.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||||
|
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||||
|
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||||
|
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
#include "lest.hpp"
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
using namespace lest;
|
||||||
|
|
||||||
|
const lest::test specification[] =
|
||||||
|
{
|
||||||
|
"Function to suppress warning \"expression has no effect\" acts as identity function", []
|
||||||
|
{
|
||||||
|
EXPECT( false == serum( false ) );
|
||||||
|
EXPECT( true == serum( true ) );
|
||||||
|
},
|
||||||
|
|
||||||
|
"Function with_message() returns correct string", []
|
||||||
|
{
|
||||||
|
std::string msg = "Let writing tests become irresistibly easy and attractive.";
|
||||||
|
EXPECT( "with message \"" + msg + "\"" == with_message( msg ) );
|
||||||
|
},
|
||||||
|
|
||||||
|
"Function of_type() returns correct string", []
|
||||||
|
{
|
||||||
|
std::string msg = "this_type";
|
||||||
|
EXPECT( "of type " + msg == of_type( msg ) );
|
||||||
|
},
|
||||||
|
|
||||||
|
"Function pluralise() adds 's' except for 1 item", []
|
||||||
|
{
|
||||||
|
std::string word = "hammer";
|
||||||
|
EXPECT( word == pluralise( 1, word ) );
|
||||||
|
for ( auto i : {0,2,3,4,5,6,7,8,9,10,11,12} )
|
||||||
|
EXPECT( word + "s" == pluralise( i, word ) );
|
||||||
|
},
|
||||||
|
|
||||||
|
"Location constructs properly", []
|
||||||
|
{
|
||||||
|
char const * file = __FILE__; int line = __LINE__;
|
||||||
|
location where{ file, line };
|
||||||
|
EXPECT( file == where.file );
|
||||||
|
EXPECT( line == where.line );
|
||||||
|
},
|
||||||
|
|
||||||
|
"Comment constructs properly", []
|
||||||
|
{
|
||||||
|
std::string text = __FILE__;
|
||||||
|
comment note = text;
|
||||||
|
EXPECT( text == note.text );
|
||||||
|
},
|
||||||
|
|
||||||
|
"Comment converted to bool indicates absence or presence of comment", []
|
||||||
|
{
|
||||||
|
EXPECT( false == bool( comment( "") ) );
|
||||||
|
EXPECT( true == bool( comment("x") ) );
|
||||||
|
},
|
||||||
|
|
||||||
|
"Failure exception type constructs and prints properly", []
|
||||||
|
{
|
||||||
|
std::string name = "test-name";
|
||||||
|
failure msg( location{"filename.cpp", 765}, "expression" );
|
||||||
|
|
||||||
|
std::ostringstream os;
|
||||||
|
report( os, msg, name );
|
||||||
|
|
||||||
|
#ifndef __GNUG__
|
||||||
|
EXPECT( os.str() == "filename.cpp(765): failed: test-name: expression\n" );
|
||||||
|
#else
|
||||||
|
EXPECT( os.str() == "filename.cpp:765: failed: test-name: expression\n" );
|
||||||
|
#endif
|
||||||
|
},
|
||||||
|
|
||||||
|
"Expected exception type constructs and prints properly", []
|
||||||
|
{
|
||||||
|
std::string name = "test-name";
|
||||||
|
expected msg( location{"filename.cpp", 765}, "expression" );
|
||||||
|
|
||||||
|
std::ostringstream os;
|
||||||
|
report( os, msg, name );
|
||||||
|
|
||||||
|
#ifndef __GNUG__
|
||||||
|
EXPECT( os.str() == "filename.cpp(765): failed: didn't get exception: test-name: expression\n" );
|
||||||
|
#else
|
||||||
|
EXPECT( os.str() == "filename.cpp:765: failed: didn't get exception: test-name: expression\n" );
|
||||||
|
#endif
|
||||||
|
},
|
||||||
|
|
||||||
|
"Unexpected exception type constructs and prints properly", []
|
||||||
|
{
|
||||||
|
std::string name = "test-name";
|
||||||
|
unexpected msg( location{"filename.cpp", 765}, "expression", "exception-type" );
|
||||||
|
|
||||||
|
std::ostringstream os;
|
||||||
|
report( os, msg, name );
|
||||||
|
|
||||||
|
#ifndef __GNUG__
|
||||||
|
EXPECT( os.str() == "filename.cpp(765): failed: got unexpected exception exception-type: test-name: expression\n" );
|
||||||
|
#else
|
||||||
|
EXPECT( os.str() == "filename.cpp:765: failed: got unexpected exception exception-type: test-name: expression\n" );
|
||||||
|
#endif
|
||||||
|
},
|
||||||
|
|
||||||
|
"Expect generates no message exception for a succeeding test", []
|
||||||
|
{
|
||||||
|
test pass = { "P", [] { EXPECT( true ); } };
|
||||||
|
|
||||||
|
try { pass.behaviour(); }
|
||||||
|
catch(...) { throw failure(location{__FILE__,__LINE__}, "unexpected error generated"); }
|
||||||
|
},
|
||||||
|
|
||||||
|
"Expect generates a message exception for a failing test", []
|
||||||
|
{
|
||||||
|
test fail = { "F", [] { EXPECT( false ); } };
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
try { fail.behaviour(); } catch ( message & ) { break; }
|
||||||
|
throw failure(location{__FILE__,__LINE__}, "no error generated");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"Expect succeeds for success (true) and failure (false)", []
|
||||||
|
{
|
||||||
|
test pass[] = {{ "P", [] { EXPECT( true ); } }};
|
||||||
|
test fail[] = {{ "F", [] { EXPECT( false ); } }};
|
||||||
|
|
||||||
|
std::ostringstream os;
|
||||||
|
|
||||||
|
EXPECT( 0 == run( pass, os ) );
|
||||||
|
EXPECT( 1 == run( fail, os ) );
|
||||||
|
},
|
||||||
|
|
||||||
|
"Expect succeeds for integer comparation", []
|
||||||
|
{
|
||||||
|
test pass [] = {{ "P" , [] { EXPECT( 7 == 7 ); EXPECT( 7 != 8 );
|
||||||
|
EXPECT( 7 >= 6 ); EXPECT( 7 <= 8 );
|
||||||
|
EXPECT( 7 > 6 ); EXPECT( 7 < 8 ); } }};
|
||||||
|
test fail_1[] = {{ "F1", [] { EXPECT( 7 == 8 ); } }};
|
||||||
|
test fail_2[] = {{ "F2", [] { EXPECT( 7 != 7 ); } }};
|
||||||
|
test fail_3[] = {{ "F3", [] { EXPECT( 7 <= 6 ); } }};
|
||||||
|
test fail_4[] = {{ "F4", [] { EXPECT( 7 >= 8 ); } }};
|
||||||
|
test fail_5[] = {{ "F5", [] { EXPECT( 7 < 6 ); } }};
|
||||||
|
test fail_6[] = {{ "F6", [] { EXPECT( 7 > 8 ); } }};
|
||||||
|
|
||||||
|
std::ostringstream os;
|
||||||
|
|
||||||
|
EXPECT( 0 == run( pass , os ) );
|
||||||
|
EXPECT( 1 == run( fail_1, os ) );
|
||||||
|
EXPECT( 1 == run( fail_2, os ) );
|
||||||
|
EXPECT( 1 == run( fail_3, os ) );
|
||||||
|
EXPECT( 1 == run( fail_4, os ) );
|
||||||
|
EXPECT( 1 == run( fail_5, os ) );
|
||||||
|
EXPECT( 1 == run( fail_6, os ) );
|
||||||
|
},
|
||||||
|
|
||||||
|
"Expect succeeds for string comparation", []
|
||||||
|
{
|
||||||
|
std::string a("a"); std::string b("b");
|
||||||
|
test pass [] = {{ "P" , [=]() { EXPECT( a == a ); EXPECT( a != b );
|
||||||
|
EXPECT( b >= a ); EXPECT( a <= b );
|
||||||
|
EXPECT( b > a ); EXPECT( a < b ); } }};
|
||||||
|
test fail_1[] = {{ "F1", [=]() { EXPECT( a == b ); } }};
|
||||||
|
test fail_2[] = {{ "F2", [=]() { EXPECT( a != a ); } }};
|
||||||
|
test fail_3[] = {{ "F3", [=]() { EXPECT( b <= a ); } }};
|
||||||
|
test fail_4[] = {{ "F4", [=]() { EXPECT( a >= b ); } }};
|
||||||
|
test fail_5[] = {{ "F5", [=]() { EXPECT( b < a ); } }};
|
||||||
|
test fail_6[] = {{ "F6", [=]() { EXPECT( a > b ); } }};
|
||||||
|
|
||||||
|
std::ostringstream os;
|
||||||
|
|
||||||
|
EXPECT( 0 == run( pass , os ) );
|
||||||
|
EXPECT( 1 == run( fail_1, os ) );
|
||||||
|
EXPECT( 1 == run( fail_2, os ) );
|
||||||
|
EXPECT( 1 == run( fail_3, os ) );
|
||||||
|
EXPECT( 1 == run( fail_4, os ) );
|
||||||
|
EXPECT( 1 == run( fail_5, os ) );
|
||||||
|
EXPECT( 1 == run( fail_6, os ) );
|
||||||
|
},
|
||||||
|
|
||||||
|
"Function run() returns the right failure count", []
|
||||||
|
{
|
||||||
|
test pass [] = {{ "P" , [] { EXPECT( 1==1 ); } }};
|
||||||
|
test fail_1[] = {{ "F1", [] { EXPECT( 0==1 ); } }};
|
||||||
|
test fail_3[] = {{ "F1", [] { EXPECT( 0==1 ); } },
|
||||||
|
{ "F2", [] { EXPECT( 0==1 ); } },
|
||||||
|
{ "F3", [] { EXPECT( 0==1 ); } },};
|
||||||
|
|
||||||
|
std::ostringstream os;
|
||||||
|
|
||||||
|
EXPECT( 0 == run( pass , os ) );
|
||||||
|
EXPECT( 1 == run( fail_1, os ) );
|
||||||
|
EXPECT( 3 == run( fail_3, os ) );
|
||||||
|
},
|
||||||
|
|
||||||
|
"Expect succeeds with an unexpected standard exception", []
|
||||||
|
{
|
||||||
|
std::string text = "hello-world";
|
||||||
|
test pass[] = {{ "P", [=]() { EXPECT( (throw std::runtime_error(text), true) ); } }};
|
||||||
|
|
||||||
|
std::ostringstream os;
|
||||||
|
|
||||||
|
EXPECT( 1 == run( pass, os ) );
|
||||||
|
EXPECT( std::string::npos != os.str().find(text) );
|
||||||
|
},
|
||||||
|
|
||||||
|
"Expect succeeds with an unexpected non-standard exception", []
|
||||||
|
{
|
||||||
|
test pass[] = {{ "P", [] { EXPECT( (throw 77, true) ); } }};
|
||||||
|
|
||||||
|
std::ostringstream os;
|
||||||
|
|
||||||
|
EXPECT( 1 == run( pass, os ) );
|
||||||
|
},
|
||||||
|
|
||||||
|
"Expect_throws succeeds with an expected standard exception", []
|
||||||
|
{
|
||||||
|
std::string text = "hello-world";
|
||||||
|
test pass[] = {{ "P", [=]() { EXPECT_THROWS( (throw std::runtime_error(text), true) ); } }};
|
||||||
|
test fail[] = {{ "F", [ ]() { EXPECT_THROWS( true ); } }};
|
||||||
|
|
||||||
|
std::ostringstream os;
|
||||||
|
|
||||||
|
EXPECT( 0 == run( pass, os ) );
|
||||||
|
EXPECT( 1 == run( fail, os ) );
|
||||||
|
},
|
||||||
|
|
||||||
|
"Expect_throws succeeds with an expected non-standard exception", []
|
||||||
|
{
|
||||||
|
test pass[] = {{ "P", [] { EXPECT_THROWS( (throw 77, true) ); } }};
|
||||||
|
test fail[] = {{ "F", [] { EXPECT_THROWS( true ); } }};
|
||||||
|
|
||||||
|
std::ostringstream os;
|
||||||
|
|
||||||
|
EXPECT( 0 == run( pass, os ) );
|
||||||
|
EXPECT( 1 == run( fail, os ) );
|
||||||
|
},
|
||||||
|
|
||||||
|
"Expect_throws_as succeeds with a specific expected standard exception", []
|
||||||
|
{
|
||||||
|
test pass[] = {{ "P", [] { EXPECT_THROWS_AS( (throw std::bad_alloc(), true), std::bad_alloc ); } }};
|
||||||
|
test fail[] = {{ "F", [] { EXPECT_THROWS_AS( (throw std::bad_alloc(), true), std::runtime_error ); } }};
|
||||||
|
|
||||||
|
std::ostringstream os;
|
||||||
|
|
||||||
|
EXPECT( 0 == run( pass, os ) );
|
||||||
|
EXPECT( 1 == run( fail, os ) );
|
||||||
|
},
|
||||||
|
|
||||||
|
"Expect_throws_as succeeds with a specific expected non-standard exception", []
|
||||||
|
{
|
||||||
|
test pass[] = {{ "P", [] { EXPECT_THROWS_AS( (throw 77, true), int ); } }};
|
||||||
|
test fail[] = {{ "F", [] { EXPECT_THROWS_AS( (throw 77, true), std::runtime_error ); } }};
|
||||||
|
|
||||||
|
std::ostringstream os;
|
||||||
|
|
||||||
|
EXPECT( 0 == run( pass, os ) );
|
||||||
|
EXPECT( 1 == run( fail, os ) );
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
return lest::run( specification );
|
||||||
|
}
|
||||||
|
|
||||||
|
// cl -nologo -Wall -EHsc test_lest.cpp && test_lest
|
||||||
|
// g++ -Wall -Wextra -Weffc++ -std=c++11 -o test_lest.exe test_lest.cpp && test_lest
|
||||||
|
|
150
test/test_line.cc
Normal file
150
test/test_line.cc
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
// This file is part of the brlaser printer driver.
|
||||||
|
//
|
||||||
|
// Copyright 2014 Peter De Wachter
|
||||||
|
//
|
||||||
|
// brlaser is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 2 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// brlaser is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with brlaser. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include "lest.hpp"
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <vector>
|
||||||
|
#include "src/line.h"
|
||||||
|
|
||||||
|
typedef std::vector<uint8_t> vec;
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t sub(uint8_t offset, uint8_t count) {
|
||||||
|
assert(offset < 16);
|
||||||
|
assert(count < 8);
|
||||||
|
return (offset << 3) | count;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t rep(uint8_t offset, uint8_t count) {
|
||||||
|
assert(offset < 4);
|
||||||
|
assert(count < 32);
|
||||||
|
return 128 | (offset << 5) | count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const lest::test specification[] = {
|
||||||
|
"Don't crash on zero-length lines",
|
||||||
|
[] {
|
||||||
|
EXPECT(( encode_line(vec{}) == vec{0xFF} ));
|
||||||
|
EXPECT(( encode_line(vec{}, vec{}) == vec{0xFF} ));
|
||||||
|
},
|
||||||
|
|
||||||
|
"Encoding an initial blank line",
|
||||||
|
[] {
|
||||||
|
EXPECT(( encode_line(vec{0,0,0}) == vec{0xFF} ));
|
||||||
|
},
|
||||||
|
|
||||||
|
"Encoding an initial non-blank line",
|
||||||
|
[] {
|
||||||
|
EXPECT(( encode_line(vec{1,2,3}) == (vec{1,sub(0,2),1,2,3}) ));
|
||||||
|
},
|
||||||
|
|
||||||
|
"Encoding a (non-initial) blank line",
|
||||||
|
[] {
|
||||||
|
EXPECT(( encode_line(vec{0,0,0}, vec{1,2,3}) == vec{0xFF} ));
|
||||||
|
},
|
||||||
|
|
||||||
|
"Encoding a repeated line",
|
||||||
|
[] {
|
||||||
|
EXPECT(( encode_line(vec{1,2,3}, vec{1,2,3}) == vec{0} ));
|
||||||
|
},
|
||||||
|
|
||||||
|
"Using a subsitute command",
|
||||||
|
[] {
|
||||||
|
EXPECT(( encode_line(vec{0,0,1,2,3,0,0}, vec(7)) == vec{1,sub(2,2),1,2,3} ));
|
||||||
|
},
|
||||||
|
|
||||||
|
"Using a repeat command",
|
||||||
|
[] {
|
||||||
|
EXPECT(( encode_line(vec{0,0,1,1,0,0}, vec(6)) == vec{1,rep(2,0),1} ));
|
||||||
|
},
|
||||||
|
|
||||||
|
"Repeat command followed by substitute command",
|
||||||
|
[] {
|
||||||
|
EXPECT(( encode_line(vec{1,1,1,2,3}, vec(5)) == vec{2,rep(0,1),1,sub(0,1),2,3} ));
|
||||||
|
},
|
||||||
|
|
||||||
|
"Substitute comand followed by repeat command",
|
||||||
|
[] {
|
||||||
|
EXPECT(( encode_line(vec{3,2,1,1,1}, vec(5)) == vec{2,sub(0,1),3,2,rep(0,1),1} ));
|
||||||
|
},
|
||||||
|
|
||||||
|
"Substitute with an unmodified byte in the middle",
|
||||||
|
[] {
|
||||||
|
EXPECT(( encode_line(vec{1,2,3,0,1,2,3}, vec(7)) == vec{1,sub(0,6),1,2,3,0,1,2,3} ));
|
||||||
|
},
|
||||||
|
|
||||||
|
"Substitue with two unmodified bytes in the middle",
|
||||||
|
[] {
|
||||||
|
EXPECT(( encode_line(vec{1,2,3,0,0,1,2,3}, vec(8)) == vec{2,sub(0,2),1,2,3,sub(2,2),1,2,3} ));
|
||||||
|
},
|
||||||
|
|
||||||
|
"Repeat with an unmodified byte in the middle",
|
||||||
|
[] {
|
||||||
|
EXPECT(( encode_line(vec{1,1,1,0,1,1,1}, vec(7)) == vec{2,rep(0,1),1,rep(1,1),1} ));
|
||||||
|
},
|
||||||
|
|
||||||
|
"254 edits needed for a single line",
|
||||||
|
[] {
|
||||||
|
vec line, result;
|
||||||
|
for (int i = 0; i < 254; ++i)
|
||||||
|
line.insert(line.end(), {0,0,1});
|
||||||
|
result.push_back(254);
|
||||||
|
for (int i = 0; i < 254; ++i)
|
||||||
|
result.insert(result.end(), {sub(2,0),1});
|
||||||
|
EXPECT(( encode_line(line, vec(line.size())) == result ));
|
||||||
|
},
|
||||||
|
|
||||||
|
"Give up if more than 254 edits needed...",
|
||||||
|
[] {
|
||||||
|
vec line, result;
|
||||||
|
for (int i = 0; i < 255; ++i)
|
||||||
|
line.insert(line.end(), {0,0,1});
|
||||||
|
result.push_back(254);
|
||||||
|
for (int i = 0; i < 253; ++i)
|
||||||
|
result.insert(result.end(), {sub(2,0),1});
|
||||||
|
result.insert(result.end(), {sub(2,3),1,0,0,1});
|
||||||
|
EXPECT(( encode_line(line, vec(line.size())) == result ));
|
||||||
|
},
|
||||||
|
|
||||||
|
"Repeat command with overflow bytes",
|
||||||
|
[] {
|
||||||
|
vec line(3, 0);
|
||||||
|
line.insert(line.end(), 512, 1);
|
||||||
|
vec ref(line.size(), 0);
|
||||||
|
vec expected{1,rep(3,31),0,255,224,1};
|
||||||
|
EXPECT(encode_line(line, ref) == expected);
|
||||||
|
},
|
||||||
|
|
||||||
|
"Substitute command with overflow bytes",
|
||||||
|
[] {
|
||||||
|
vec expected{1,sub(15,7),255,0,255,237};
|
||||||
|
vec line(270, 0);
|
||||||
|
for (int i = 0; i < 250; ++i) {
|
||||||
|
expected.insert(expected.end(), {1,2});
|
||||||
|
line.insert(line.end(), {1,2});
|
||||||
|
}
|
||||||
|
vec ref(line.size(), 0);
|
||||||
|
EXPECT(encode_line(line, ref) == expected);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
return lest::run(specification);
|
||||||
|
}
|
Reference in New Issue
Block a user