Skip to content

Commit

Permalink
Add some basic tests
Browse files Browse the repository at this point in the history
  • Loading branch information
pdewacht committed Feb 4, 2014
1 parent bb1ba17 commit 5159844
Show file tree
Hide file tree
Showing 6 changed files with 784 additions and 0 deletions.
17 changes: 17 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,20 @@ rastertobrlaser_LDADD = $(CUPS_LIBS)

brdecode_SOURCES = \
src/brdecode.cc


TESTS = test_lest test_line test_block
check_PROGRAMS = $(TESTS)
test_lest_SOURCES = \
test/test_lest.cc \
test/lest.h
test_line_SOURCES = \
test/test_line.cc \
src/line.h \
src/line.cc \
test/lest.h
test_block_SOURCES = \
test/test_block.cc \
src/block.h \
test/tempfile.h \
test/lest.h
197 changes: 197 additions & 0 deletions test/lest.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
// 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( 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 changes: 54 additions & 0 deletions test/tempfile.h
Original file line number Diff line number Diff line change
@@ -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 changes: 75 additions & 0 deletions test/test_block.cc
Original file line number Diff line number Diff line change
@@ -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);
}
Loading

0 comments on commit 5159844

Please sign in to comment.