1
0
mirror of https://github.com/Zygo/bees.git synced 2025-06-16 01:26:18 +02:00

bees: remove local cruft, throw at github

This commit is contained in:
Zygo Blaxell
2016-11-15 23:32:44 -05:00
commit cca0ee26a8
66 changed files with 12785 additions and 0 deletions

5
test/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
*
!Makefile
!*.c
!*.cc
!*.h

36
test/Makefile Normal file
View File

@ -0,0 +1,36 @@
PROGRAMS = \
chatter \
crc64 \
execpipe \
fd \
interp \
limits \
path \
process \
all: test
test: $(PROGRAMS)
set -x; for prog in $(PROGRAMS); do ./$$prog || exit 1; done
include ../makeflags
LIBS = -lcrucible
LDFLAGS = -L../lib -Wl,-rpath=$(shell realpath ../lib)
depends.mk: *.cc
for x in *.cc; do $(CXX) $(CXXFLAGS) -M "$$x"; done >> depends.mk.new
mv -fv depends.mk.new depends.mk
-include depends.mk
%.o: %.cc %.h ../makeflags
-echo "Implicit rule %.o: %.cc" >&2
$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
%: %.o ../makeflags
-echo "Implicit rule %: %.o" >&2
$(CXX) $(CXXFLAGS) -o "$@" "$<" $(LDFLAGS) $(LIBS)
clean:
-rm -fv *.o

49
test/chatter.cc Normal file
View File

@ -0,0 +1,49 @@
#include "tests.h"
#include "crucible/chatter.h"
#include <ios>
#include <cassert>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
using namespace crucible;
static
void
test_chatter_one()
{
cerr << endl;
CHATTER("simple chatter case");
}
static
void
test_chatter_two()
{
cerr << endl;
CHATTER("two lines\nof chatter");
}
static
void
test_chatter_three()
{
cerr << endl;
Chatter c("tct");
c << "More complicated";
c << "\ncase with\n";
c << "some \\ns";
}
int
main(int, char**)
{
RUN_A_TEST(test_chatter_one());
RUN_A_TEST(test_chatter_two());
RUN_A_TEST(test_chatter_three());
exit(EXIT_SUCCESS);
}

39
test/crc64.cc Normal file
View File

@ -0,0 +1,39 @@
#include "tests.h"
#include "crucible/crc64.h"
#include <cassert>
using namespace crucible;
static
void
test_getcrc64_strings()
{
assert(Digest::CRC::crc64("John") == 5942451273432301568);
assert(Digest::CRC::crc64("Paul") == 5838402100630913024);
assert(Digest::CRC::crc64("George") == 6714394476893704192);
assert(Digest::CRC::crc64("Ringo") == 6038837226071130112);
assert(Digest::CRC::crc64("") == 0);
assert(Digest::CRC::crc64("\377\277\300\200") == 15615382887346470912ULL);
}
static
void
test_getcrc64_byte_arrays()
{
assert(Digest::CRC::crc64("John", 4) == 5942451273432301568);
assert(Digest::CRC::crc64("Paul", 4) == 5838402100630913024);
assert(Digest::CRC::crc64("George", 6) == 6714394476893704192);
assert(Digest::CRC::crc64("Ringo", 5) == 6038837226071130112);
assert(Digest::CRC::crc64("", 0) == 0);
assert(Digest::CRC::crc64("\377\277\300\200", 4) == 15615382887346470912ULL);
}
int
main(int, char**)
{
RUN_A_TEST(test_getcrc64_strings());
RUN_A_TEST(test_getcrc64_byte_arrays());
exit(EXIT_SUCCESS);
}

64
test/execpipe.cc Normal file
View File

@ -0,0 +1,64 @@
#include "tests.h"
#include "crucible/execpipe.h"
#include <ios>
#include <cassert>
#include <cstring>
#include <cstdlib>
#include <stdexcept>
#include <unistd.h>
using namespace crucible;
using namespace std;
#if 1 // Needs rework
static inline
void
test_hello_world()
{
// alarm(9);
Fd fd = popen([]() { return system("echo Hello, World!"); });
char buf[1024];
size_t rv = -1;
read_partial_or_die(fd, buf, rv);
assert(rv > 0);
string b(buf, buf + rv - 1);
// cerr << "hello_world says: '" << b << "'" << endl;
assert(b == "Hello, World!");
}
static inline
void
test_read_limit(size_t limit = 4096)
{
alarm(9);
Fd fd = popen([]() { return system("yes Hello!"); });
try {
string b = read_all(fd, limit);
} catch (out_of_range &re) {
return;
}
assert(!"no exception thrown by read_all");
}
#endif
namespace crucible {
extern bool assert_no_leaked_fds();
};
int
main(int, char**)
{
#if 1
RUN_A_TEST(test_hello_world());
assert(assert_no_leaked_fds());
RUN_A_TEST(test_read_limit(4095));
RUN_A_TEST(test_read_limit(4096));
RUN_A_TEST(test_read_limit(4097));
assert(assert_no_leaked_fds());
#endif
exit(EXIT_SUCCESS);
}

393
test/fd.cc Normal file
View File

@ -0,0 +1,393 @@
// TEST DATA DO NOT REMOVE THIS LINE
#include "tests.h"
#include "crucible/chatter.h"
#include "crucible/error.h"
#include "crucible/fd.h"
#include <cassert>
#include <cstring>
#include <cstdlib>
#include <ios>
#include <map>
#include <string>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
using namespace crucible;
static
void
test_default_constructor_and_destructor()
{
Fd f;
}
static
void
test_basic_read()
{
Fd f = open_or_die("fd.cc");
const char test_string[] = "// TEST DATA DO NOT REMOVE THIS LINE";
const int test_string_len = sizeof(test_string) - 1;
char read_buf[test_string_len];
read_or_die(f, read_buf);
assert(!strncmp(read_buf, test_string, test_string_len));
f->close();
}
static
void
test_create_read_write()
{
Fd f = open_or_die("tmp/fd-read-write", O_CREAT | O_RDWR | O_TRUNC);
struct test_str_out {
int i;
float f;
} tso = {
.i = 5,
.f = 3.14159,
}, tsi = {
.i = 0,
.f = 0,
};
size_t bytes_read = 0;
read_partial_or_die(f, tsi, bytes_read);
assert(bytes_read == 0);
assert(tsi.i == 0);
assert(tsi.f == 0);
pwrite_or_die(f, tso, 1024);
pread_or_die(f, tsi, 1024);
assert(!memcmp(&tsi, &tso, sizeof(tsi)));
}
static
void
test_flags()
{
#define FLAG_TEST(x) cerr << #x << ": " << flush; cerr << x << endl;
FLAG_TEST(o_flags_ntoa(O_RDONLY));
FLAG_TEST(o_flags_ntoa(O_WRONLY));
FLAG_TEST(o_flags_ntoa(O_RDWR));
FLAG_TEST(o_flags_ntoa(O_CREAT|O_WRONLY|O_TRUNC));
FLAG_TEST(o_mode_ntoa(0001));
FLAG_TEST(o_mode_ntoa(0002));
FLAG_TEST(o_mode_ntoa(0004));
FLAG_TEST(o_mode_ntoa(0010));
FLAG_TEST(o_mode_ntoa(0020));
FLAG_TEST(o_mode_ntoa(0040));
FLAG_TEST(o_mode_ntoa(0100));
FLAG_TEST(o_mode_ntoa(0200));
FLAG_TEST(o_mode_ntoa(0400));
FLAG_TEST(o_mode_ntoa(01000));
FLAG_TEST(o_mode_ntoa(02000));
FLAG_TEST(o_mode_ntoa(04000));
FLAG_TEST(o_mode_ntoa(010000));
FLAG_TEST(o_mode_ntoa(020000));
FLAG_TEST(o_mode_ntoa(040000));
FLAG_TEST(o_mode_ntoa(0777));
FLAG_TEST(o_mode_ntoa(02775));
FLAG_TEST(o_mode_ntoa(01777));
FLAG_TEST(o_mode_ntoa(022));
FLAG_TEST(o_mode_ntoa(077));
}
// Test code
namespace crucible {
extern bool assert_no_leaked_fds();
};
struct FdChecker {
~FdChecker()
{
assert_no_leaked_fds();
}
};
static FdChecker fd_destructor_check;
static inline void assert_is_closed(int i, bool closed = true)
{
pid_t self_pid = getpid();
char buf[1024];
snprintf(buf, sizeof(buf), "/proc/%d/fd/%d", self_pid, i);
assert(access(buf, F_OK) ? closed : !closed);
}
static void test_construct_destroy()
{
int i;
{
Fd fd(open("fd.cc", O_RDONLY));
i = fd;
}
assert_is_closed(i);
}
static void test_construct_copy()
{
int i;
{
Fd fd(open("fd.cc", O_RDONLY));
i = fd;
Fd fd2(fd);
int j = fd2;
assert(i == j);
}
assert_is_closed(i);
}
static void test_construct_default_assign()
{
int i;
{
i = open("fd.cc", O_RDONLY);
Fd fd;
fd = i;
Fd fd2;
fd2 = fd;
int j = fd2;
assert(i == j);
}
assert_is_closed(i);
}
static void test_assign_int()
{
int i;
{
i = open("fd.cc", O_RDONLY);
Fd fd;
fd = i;
Fd fd2;
fd2 = i;
int j = fd2;
assert(i == j);
}
assert_is_closed(i);
}
static void test_assign_int_survives_scope()
{
int i, j;
{
Fd fd2;
{
i = open("fd.cc", O_RDONLY);
Fd fd;
fd = i;
fd2 = i;
j = fd2;
assert(i == j);
}
assert_is_closed(i, false);
}
assert_is_closed(i, true);
}
static void test_assign_int_close()
{
int i;
{
Fd fd(open("fd.cc", O_RDONLY));
i = fd;
assert_is_closed(i, false);
fd = -1;
assert_is_closed(i, true);
int j = fd;
assert(j == -1);
// Bonus conversion operator tests
assert(fd == -1);
// Chasing a closed ref now triggers an exception
assert(catch_all([&]() { return fd->get_fd() == -1; }));
}
assert_is_closed(i, true);
}
static void test_assign_int_close_2()
{
int i;
{
Fd fd(open("fd.cc", O_RDONLY));
i = fd;
assert_is_closed(i, false);
// -2 is null...
fd = -2;
assert_is_closed(i, true);
int j = fd;
// ...but it will come back as -1
assert(j == -1);
// Bonus conversion operator tests
assert(fd == -1);
// Chasing a closed ref now triggers an exception
assert(catch_all([&]() { return fd->get_fd() == -1; }));
}
assert_is_closed(i, true);
}
static void test_map()
{
int a, b, c;
map<string, Fd> fds;
{
Fd fd_dot_cc = open("fd.cc", O_RDONLY);
a = fd_dot_cc;
assert_is_closed(a, false);
Fd fd_tests_h = open("tests.h", O_RDONLY);
b = fd_tests_h;
assert_is_closed(b, false);
Fd fd_makefile = open("Makefile", O_RDONLY);
c = fd_makefile;
assert_is_closed(c, false);
fds["fd.cc"] = fd_dot_cc;
fds.insert(make_pair("tests.h", fd_tests_h));
int j = fds["Makefile"];
assert(j == -1);
fds["Makefile"] = fd_makefile;
assert_is_closed(a, false);
assert_is_closed(b, false);
assert_is_closed(c, false);
}
assert_is_closed(a, false);
assert_is_closed(b, false);
assert_is_closed(c, false);
}
static void test_close_method()
{
Fd fd = open("fd.cc", O_RDONLY);
int i = fd;
assert_is_closed(i, false);
fd->close();
assert_is_closed(i, true);
}
static void test_shared_close_method()
{
Fd fd = open("fd.cc", O_RDONLY);
int i = fd;
Fd fd2 = fd;
assert_is_closed(i, false);
assert_is_closed(fd2, false);
fd->close();
assert_is_closed(i, true);
assert_is_closed(fd2, true);
}
struct DerivedFdResource : public Fd::resource_type {
string m_name;
DerivedFdResource(string name) : m_name(name) {
Fd::resource_type::operator=(open(name.c_str(), O_RDONLY));
assert_is_closed(this->get_fd(), false);
}
const string &name() const { return m_name; }
};
struct DerivedFd : public Fd {
using resource_type = DerivedFdResource;
DerivedFd(string name) {
shared_ptr<DerivedFdResource> ptr = make_shared<DerivedFdResource>(name);
Fd::operator=(static_pointer_cast<Fd::resource_type>(ptr));
}
shared_ptr<DerivedFdResource> operator->() const {
shared_ptr<DerivedFdResource> rv = cast<DerivedFdResource>();
THROW_CHECK1(out_of_range, rv, rv);
return rv;
}
private:
DerivedFd() = default;
};
static void test_derived_resource_type()
{
DerivedFd fd("fd.cc");
assert_is_closed(fd, false);
assert(fd->name() == "fd.cc");
DerivedFd fd3(fd);
assert_is_closed(fd, false);
assert_is_closed(fd3, false);
Fd fd2(fd3);
assert_is_closed(fd, false);
assert_is_closed(fd2, false);
assert_is_closed(fd3, false);
}
static void test_derived_cast()
{
DerivedFd fd("fd.cc");
assert_is_closed(fd, false);
Fd fd2(fd);
Fd fd3 = open("fd.cc", O_RDONLY);
assert(fd->name() == "fd.cc");
assert(fd.cast<Fd::resource_type>());
assert(fd.cast<DerivedFd::resource_type>());
assert(fd2.cast<Fd::resource_type>());
assert(fd2.cast<DerivedFd::resource_type>());
assert(fd3.cast<Fd::resource_type>());
assert(catch_all([&](){ assert(!fd3.cast<DerivedFd::resource_type>()); } ));
}
static void test_derived_map()
{
int a, b, c;
map<string, Fd> fds;
{
DerivedFd fd_dot_cc("fd.cc");
a = fd_dot_cc;
assert_is_closed(a, false);
Fd fd_tests_h = open("tests.h", O_RDONLY);
b = fd_tests_h;
assert_is_closed(b, false);
DerivedFd fd_makefile("Makefile");
c = fd_makefile;
assert_is_closed(c, false);
fds["fd.cc"] = fd_dot_cc;
fds.insert(make_pair("tests.h", fd_tests_h));
int j = fds["Makefile"];
assert(j == -1);
fds["Makefile"] = fd_makefile;
assert_is_closed(a, false);
assert_is_closed(b, false);
assert_is_closed(c, false);
}
assert_is_closed(a, false);
assert_is_closed(b, false);
assert_is_closed(c, false);
}
int main(int, const char **)
{
RUN_A_TEST(test_default_constructor_and_destructor());
RUN_A_TEST(test_basic_read());
RUN_A_TEST(test_create_read_write());
RUN_A_TEST(test_flags());
RUN_A_TEST(test_construct_destroy());
RUN_A_TEST(test_construct_copy());
RUN_A_TEST(test_construct_default_assign());
RUN_A_TEST(test_assign_int());
RUN_A_TEST(test_assign_int_survives_scope());
RUN_A_TEST(test_assign_int_close());
RUN_A_TEST(test_assign_int_close_2());
RUN_A_TEST(test_map());
RUN_A_TEST(test_close_method());
RUN_A_TEST(test_shared_close_method());
RUN_A_TEST(test_derived_resource_type());
RUN_A_TEST(test_derived_map());
RUN_A_TEST(test_derived_cast());
assert_no_leaked_fds();
return 0;
}

88
test/interp.cc Normal file
View File

@ -0,0 +1,88 @@
#include "tests.h"
#include "crucible/interp.h"
using namespace crucible;
using namespace std;
/***********************************************************************
How this should work:
Interpreter reads an arg list:
argv[0] --method0args --method1arg arg1 --method1arg=arg1 -- args...
argv[0] should look up a shared_ptr<Command> which creates an object of
type shared_ptr<Process>. This object is used to receive args by
method calls or one at a time.
<Command> and <Process> can be the same object, or not.
Process p methods:
p->spawn(Interp*) -> Process
p->exec(ArgList) -> Process / Result
p->method (from ArgParser<>)
p->finish() -> void (destroys object without early destruction warnings...?)
p->~Process() -> complains loudly if finish() not called first...?
Result might be a pair of Process, string. Or just string.
ArgParser should be more like GetOpt:
build a dictionary and an arg list from arguments
Process methods should interrogate ArgParser
ArgParser might have a table of boolean and string option names so it can reject invalid options
but if it had that, we could also pass in Process and have it call methods on it
...but that is a _lot_ of pointer-hiding when we could KISS
...but if we had that solved, argparser tables look like lists of method names
ArgParser<T> has a table of names and methods on object of type T
ArgParser hides everything behind void* and hands off to a compiled implementation to do callbacks
Extreme simplification: arguments are themselves executable
so '--method_foo arg' really means construct MethodFoo(arg) and cast to shared_ptr<ProcArg>
then Process->invokeSomething(ProcArg)
too extreme, use argparser instead
***********************************************************************/
void
test_arg_parser()
{
ArgParser ap;
ArgList al( { "abc", "--def", "ghi" } );
ap.parse(NULL, al);
}
struct Thing {
int m_i;
double m_d;
string m_s;
void set_i(int i) { cerr << "i = " << i << endl; m_i = i; }
void set_d(double d) { cerr << "d = " << d << endl; m_d = d; }
void set_s(string s) { cerr << "s = " << s << endl; m_s = s; }
};
template <typename F, typename T, typename A>
void
assign(T& t, F f, A a)
{
cerr << __PRETTY_FUNCTION__ << " - a = " << a << endl;
(t.*f)(a);
}
int
main(int, char**)
{
RUN_A_TEST(test_arg_parser());
Thing p;
assign(p, &Thing::set_i, 5);
cerr << "p.m_i = " << p.m_i << endl;
exit(EXIT_SUCCESS);
}

325
test/limits.cc Normal file
View File

@ -0,0 +1,325 @@
#include "tests.h"
#include "crucible/error.h"
#include "crucible/limits.h"
#include <cassert>
using namespace crucible;
// Like catch_all but don't bother printing anything
static
int
silent_catch_all(const function<void()> &f)
{
try {
f();
return 0;
} catch (const exception &) {
return 1;
} catch (...) {
return -1;
}
}
#define SHOULD_FAIL(expr) assert(1 == silent_catch_all([&]() { (expr); }))
#define SHOULD_PASS(expr, result) assert(0 == silent_catch_all([&]() { assert((result) == (expr)); }))
static
void
test_cast_signed_negative_to_unsigned()
{
off_t tv = -1;
SHOULD_FAIL(ranged_cast<uint64_t>(tv));
SHOULD_FAIL(ranged_cast<uint32_t>(tv));
SHOULD_FAIL(ranged_cast<uint16_t>(tv));
SHOULD_FAIL(ranged_cast<uint8_t>(tv));
SHOULD_FAIL(ranged_cast<unsigned long long>(tv));
SHOULD_FAIL(ranged_cast<unsigned long>(tv));
SHOULD_FAIL(ranged_cast<unsigned int>(tv));
SHOULD_FAIL(ranged_cast<unsigned short>(tv));
SHOULD_FAIL(ranged_cast<unsigned char>(tv));
}
static
void
test_cast_1_to_things()
{
auto tv = 1;
SHOULD_PASS(ranged_cast<off_t>(tv), 1);
SHOULD_PASS(ranged_cast<uint64_t>(tv), 1);
SHOULD_PASS(ranged_cast<uint32_t>(tv), 1);
SHOULD_PASS(ranged_cast<uint16_t>(tv), 1);
SHOULD_PASS(ranged_cast<uint8_t>(tv), 1);
SHOULD_PASS(ranged_cast<int64_t>(tv), 1);
SHOULD_PASS(ranged_cast<int32_t>(tv), 1);
SHOULD_PASS(ranged_cast<int16_t>(tv), 1);
SHOULD_PASS(ranged_cast<int8_t>(tv), 1);
SHOULD_PASS(ranged_cast<unsigned long long>(tv), 1);
SHOULD_PASS(ranged_cast<unsigned long>(tv), 1);
SHOULD_PASS(ranged_cast<unsigned int>(tv), 1);
SHOULD_PASS(ranged_cast<unsigned short>(tv), 1);
SHOULD_PASS(ranged_cast<unsigned char>(tv), 1);
SHOULD_PASS(ranged_cast<signed long long>(tv), 1);
SHOULD_PASS(ranged_cast<signed long>(tv), 1);
SHOULD_PASS(ranged_cast<signed int>(tv), 1);
SHOULD_PASS(ranged_cast<signed short>(tv), 1);
SHOULD_PASS(ranged_cast<signed char>(tv), 1);
}
static
void
test_cast_128_to_things()
{
auto tv = 128;
SHOULD_PASS(ranged_cast<off_t>(tv), 128);
SHOULD_PASS(ranged_cast<uint64_t>(tv), 128);
SHOULD_PASS(ranged_cast<uint32_t>(tv), 128);
SHOULD_PASS(ranged_cast<uint16_t>(tv), 128);
SHOULD_PASS(ranged_cast<uint8_t>(tv), 128);
SHOULD_PASS(ranged_cast<int64_t>(tv), 128);
SHOULD_PASS(ranged_cast<int32_t>(tv), 128);
SHOULD_PASS(ranged_cast<int16_t>(tv), 128);
SHOULD_FAIL(ranged_cast<int8_t>(tv));
SHOULD_PASS(ranged_cast<unsigned long long>(tv), 128);
SHOULD_PASS(ranged_cast<unsigned long>(tv), 128);
SHOULD_PASS(ranged_cast<unsigned int>(tv), 128);
SHOULD_PASS(ranged_cast<unsigned short>(tv), 128);
SHOULD_PASS(ranged_cast<unsigned char>(tv), 128);
SHOULD_PASS(ranged_cast<signed long long>(tv), 128);
SHOULD_PASS(ranged_cast<signed long>(tv), 128);
SHOULD_PASS(ranged_cast<signed int>(tv), 128);
SHOULD_PASS(ranged_cast<signed short>(tv), 128);
SHOULD_FAIL(ranged_cast<signed char>(tv));
}
static
void
test_cast_256_to_things()
{
auto tv = 256;
SHOULD_PASS(ranged_cast<off_t>(tv), 256);
SHOULD_PASS(ranged_cast<uint64_t>(tv), 256);
SHOULD_PASS(ranged_cast<uint32_t>(tv), 256);
SHOULD_PASS(ranged_cast<uint16_t>(tv), 256);
SHOULD_FAIL(ranged_cast<uint8_t>(tv));
SHOULD_PASS(ranged_cast<int64_t>(tv), 256);
SHOULD_PASS(ranged_cast<int32_t>(tv), 256);
SHOULD_PASS(ranged_cast<int16_t>(tv), 256);
SHOULD_FAIL(ranged_cast<int8_t>(tv));
SHOULD_PASS(ranged_cast<unsigned long long>(tv), 256);
SHOULD_PASS(ranged_cast<unsigned long>(tv), 256);
SHOULD_PASS(ranged_cast<unsigned int>(tv), 256);
SHOULD_PASS(ranged_cast<unsigned short>(tv), 256);
SHOULD_FAIL(ranged_cast<unsigned char>(tv));
SHOULD_PASS(ranged_cast<signed long long>(tv), 256);
SHOULD_PASS(ranged_cast<signed long>(tv), 256);
SHOULD_PASS(ranged_cast<signed int>(tv), 256);
SHOULD_PASS(ranged_cast<signed short>(tv), 256);
SHOULD_FAIL(ranged_cast<signed char>(tv));
}
static
void
test_cast_0x80000000_to_things()
{
auto sv = 0x80000000LL;
auto uv = 0x80000000ULL;
SHOULD_PASS(ranged_cast<off_t>(sv), sv);
SHOULD_PASS(ranged_cast<uint64_t>(uv), uv);
SHOULD_PASS(ranged_cast<uint32_t>(uv), uv);
SHOULD_FAIL(ranged_cast<uint16_t>(uv));
SHOULD_FAIL(ranged_cast<uint8_t>(uv));
SHOULD_PASS(ranged_cast<int64_t>(sv), sv);
SHOULD_FAIL(ranged_cast<int32_t>(sv));
SHOULD_FAIL(ranged_cast<int16_t>(sv));
SHOULD_FAIL(ranged_cast<int8_t>(sv));
SHOULD_PASS(ranged_cast<unsigned long long>(uv), uv);
SHOULD_PASS(ranged_cast<unsigned long>(uv), uv);
SHOULD_PASS(ranged_cast<unsigned int>(uv), uv);
SHOULD_FAIL(ranged_cast<unsigned short>(uv));
SHOULD_FAIL(ranged_cast<unsigned char>(uv));
SHOULD_PASS(ranged_cast<signed long long>(sv), sv);
SHOULD_PASS(ranged_cast<signed long>(sv), sv);
SHOULD_FAIL(ranged_cast<signed short>(sv));
SHOULD_FAIL(ranged_cast<signed char>(sv));
if (sizeof(int) == 4) {
SHOULD_FAIL(ranged_cast<signed int>(sv));
} else if (sizeof(int) == 8) {
SHOULD_PASS(ranged_cast<signed int>(sv), sv);
} else {
assert(!"unhandled case, please add code here");
}
}
static
void
test_cast_0xffffffff_to_things()
{
auto sv = 0xffffffffLL;
auto uv = 0xffffffffULL;
SHOULD_PASS(ranged_cast<off_t>(sv), sv);
SHOULD_PASS(ranged_cast<uint64_t>(uv), uv);
SHOULD_PASS(ranged_cast<uint32_t>(uv), uv);
SHOULD_FAIL(ranged_cast<uint16_t>(uv));
SHOULD_FAIL(ranged_cast<uint8_t>(uv));
SHOULD_PASS(ranged_cast<int64_t>(sv), sv);
SHOULD_FAIL(ranged_cast<int32_t>(sv));
SHOULD_FAIL(ranged_cast<int16_t>(sv));
SHOULD_FAIL(ranged_cast<int8_t>(sv));
SHOULD_PASS(ranged_cast<unsigned long long>(uv), uv);
SHOULD_PASS(ranged_cast<unsigned long>(uv), uv);
SHOULD_PASS(ranged_cast<unsigned int>(uv), uv);
SHOULD_FAIL(ranged_cast<unsigned short>(uv));
SHOULD_FAIL(ranged_cast<unsigned char>(uv));
SHOULD_PASS(ranged_cast<signed long long>(sv), sv);
SHOULD_PASS(ranged_cast<signed long>(sv), sv);
SHOULD_FAIL(ranged_cast<signed short>(sv));
SHOULD_FAIL(ranged_cast<signed char>(sv));
if (sizeof(int) == 4) {
SHOULD_FAIL(ranged_cast<signed int>(sv));
} else if (sizeof(int) == 8) {
SHOULD_PASS(ranged_cast<signed int>(sv), sv);
} else {
assert(!"unhandled case, please add code here");
}
}
static
void
test_cast_0xfffffffff_to_things()
{
auto sv = 0xfffffffffLL;
auto uv = 0xfffffffffULL;
SHOULD_PASS(ranged_cast<off_t>(sv), sv);
SHOULD_PASS(ranged_cast<uint64_t>(uv), uv);
SHOULD_FAIL(ranged_cast<uint32_t>(uv));
SHOULD_FAIL(ranged_cast<uint16_t>(uv));
SHOULD_FAIL(ranged_cast<uint8_t>(uv));
SHOULD_PASS(ranged_cast<int64_t>(sv), sv);
SHOULD_FAIL(ranged_cast<int32_t>(sv));
SHOULD_FAIL(ranged_cast<int16_t>(sv));
SHOULD_FAIL(ranged_cast<int8_t>(sv));
SHOULD_PASS(ranged_cast<unsigned long long>(uv), uv);
SHOULD_FAIL(ranged_cast<unsigned short>(uv));
SHOULD_FAIL(ranged_cast<unsigned char>(uv));
SHOULD_PASS(ranged_cast<signed long long>(sv), sv);
SHOULD_FAIL(ranged_cast<signed short>(sv));
SHOULD_FAIL(ranged_cast<signed char>(sv));
if (sizeof(int) == 4) {
SHOULD_FAIL(ranged_cast<signed int>(sv));
SHOULD_FAIL(ranged_cast<unsigned int>(uv));
} else if (sizeof(int) == 8) {
SHOULD_PASS(ranged_cast<signed int>(sv), sv);
SHOULD_PASS(ranged_cast<unsigned int>(uv), uv);
} else {
assert(!"unhandled case, please add code here");
}
if (sizeof(long) == 4) {
SHOULD_FAIL(ranged_cast<signed long>(sv));
SHOULD_FAIL(ranged_cast<unsigned long>(uv));
} else if (sizeof(long) == 8) {
SHOULD_PASS(ranged_cast<signed long>(sv), sv);
SHOULD_PASS(ranged_cast<unsigned long>(uv), uv);
} else {
assert(!"unhandled case, please add code here");
}
}
static
void
test_cast_0x8000000000000000_to_things()
{
auto sv = 0x8000000000000000LL;
auto uv = 0x8000000000000000ULL;
SHOULD_FAIL(ranged_cast<off_t>(sv));
SHOULD_PASS(ranged_cast<uint64_t>(uv), uv);
SHOULD_FAIL(ranged_cast<uint32_t>(uv));
SHOULD_FAIL(ranged_cast<uint16_t>(uv));
SHOULD_FAIL(ranged_cast<uint8_t>(uv));
SHOULD_FAIL(ranged_cast<int64_t>(sv));
SHOULD_FAIL(ranged_cast<int32_t>(sv));
SHOULD_FAIL(ranged_cast<int16_t>(sv));
SHOULD_FAIL(ranged_cast<int8_t>(sv));
SHOULD_PASS(ranged_cast<unsigned long long>(uv), uv);
SHOULD_FAIL(ranged_cast<unsigned short>(uv));
SHOULD_FAIL(ranged_cast<unsigned char>(uv));
SHOULD_FAIL(ranged_cast<signed long long>(sv));
SHOULD_FAIL(ranged_cast<signed long>(sv));
SHOULD_FAIL(ranged_cast<signed int>(sv));
SHOULD_FAIL(ranged_cast<signed short>(sv));
SHOULD_FAIL(ranged_cast<signed char>(sv));
if (sizeof(int) == 4) {
SHOULD_FAIL(ranged_cast<unsigned int>(uv));
} else if (sizeof(int) == 8) {
SHOULD_PASS(ranged_cast<unsigned int>(uv), uv);
} else {
assert(!"unhandled case, please add code here");
}
if (sizeof(long) == 4) {
SHOULD_FAIL(ranged_cast<unsigned long>(uv));
} else if (sizeof(long) == 8) {
SHOULD_PASS(ranged_cast<unsigned long>(uv), uv);
} else {
assert(!"unhandled case, please add code here");
}
}
static
void
test_cast_0xffffffffffffffff_to_things()
{
auto sv = 0xffffffffffffffffLL;
auto uv = 0xffffffffffffffffULL;
SHOULD_FAIL(ranged_cast<off_t>(sv));
SHOULD_PASS(ranged_cast<uint64_t>(uv), uv);
SHOULD_FAIL(ranged_cast<uint32_t>(uv));
SHOULD_FAIL(ranged_cast<uint16_t>(uv));
SHOULD_FAIL(ranged_cast<uint8_t>(uv));
SHOULD_FAIL(ranged_cast<int64_t>(sv));
SHOULD_FAIL(ranged_cast<int32_t>(sv));
SHOULD_FAIL(ranged_cast<int16_t>(sv));
SHOULD_FAIL(ranged_cast<int8_t>(sv));
SHOULD_PASS(ranged_cast<unsigned long long>(uv), uv);
SHOULD_FAIL(ranged_cast<unsigned short>(uv));
SHOULD_FAIL(ranged_cast<unsigned char>(uv));
SHOULD_FAIL(ranged_cast<signed long long>(sv));
SHOULD_FAIL(ranged_cast<signed long>(sv));
SHOULD_FAIL(ranged_cast<signed int>(sv));
SHOULD_FAIL(ranged_cast<signed short>(sv));
SHOULD_FAIL(ranged_cast<signed char>(sv));
if (sizeof(int) == 4) {
SHOULD_FAIL(ranged_cast<unsigned int>(uv));
} else if (sizeof(int) == 8) {
SHOULD_PASS(ranged_cast<unsigned int>(uv), uv);
} else {
assert(!"unhandled case, please add code here");
}
if (sizeof(long) == 4) {
SHOULD_FAIL(ranged_cast<unsigned long>(uv));
} else if (sizeof(long) == 8) {
SHOULD_PASS(ranged_cast<unsigned long>(uv), uv);
} else {
assert(!"unhandled case, please add code here");
}
}
// OK enough with the small values. We want to know if 32-bit machines break.
int
main(int, char**)
{
RUN_A_TEST(test_cast_signed_negative_to_unsigned());
RUN_A_TEST(test_cast_1_to_things());
RUN_A_TEST(test_cast_128_to_things());
RUN_A_TEST(test_cast_256_to_things());
RUN_A_TEST(test_cast_0x80000000_to_things());
RUN_A_TEST(test_cast_0xffffffff_to_things());
RUN_A_TEST(test_cast_0xfffffffff_to_things());
RUN_A_TEST(test_cast_0x8000000000000000_to_things());
RUN_A_TEST(test_cast_0xffffffffffffffff_to_things());
exit(EXIT_SUCCESS);
}

40
test/path.cc Normal file
View File

@ -0,0 +1,40 @@
#include "tests.h"
#include "crucible/path.h"
#include <ios>
#include <cassert>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
using namespace crucible;
unsigned failures = 0;
static
void
test_path_basename(string input, string expected)
{
string result = basename(input);
if (expected != result) {
std::cerr << "result was \"" << result << "\"" << std::endl;
++failures;
}
}
int
main(int, char**)
{
RUN_A_TEST(test_path_basename("/foo/bar.c", "bar.c"));
RUN_A_TEST(test_path_basename("/foo/bar/", ""));
RUN_A_TEST(test_path_basename("/foo/", ""));
RUN_A_TEST(test_path_basename("/", ""));
RUN_A_TEST(test_path_basename("foo/bar.c", "bar.c"));
RUN_A_TEST(test_path_basename("bar.c", "bar.c"));
RUN_A_TEST(test_path_basename("", ""));
assert(!failures);
exit(EXIT_SUCCESS);
}

65
test/process.cc Normal file
View File

@ -0,0 +1,65 @@
#include "tests.h"
#include "crucible/process.h"
#include <ios>
#include <cassert>
#include <cstring>
#include <cstdlib>
#include <stdexcept>
#include <unistd.h>
using namespace crucible;
using namespace std;
static inline
int
return_value(int val)
{
// cerr << "pid " << getpid() << " returning " << val << endl;
return val;
}
static inline
int
return_value_2(int val, int val2)
{
return val + val2;
}
static inline
void
test_fork_return(int val)
{
Pid child(return_value, val);
assert(child == child->get_id());
assert(child == child->native_handle());
int status = child->join();
int rv_status = WEXITSTATUS(status);
assert(WIFEXITED(status));
assert(rv_status == val);
}
static inline
void
test_fork_return(int val, int val2)
{
Pid child(return_value_2, val, val2);
int status = child->join();
int rv_status = WEXITSTATUS(status);
assert(WIFEXITED(status));
assert(rv_status == val + val2);
}
int
main(int, char**)
{
RUN_A_TEST(test_fork_return(0));
RUN_A_TEST(test_fork_return(1));
RUN_A_TEST(test_fork_return(9));
RUN_A_TEST(test_fork_return(2, 3));
RUN_A_TEST(test_fork_return(7, 9));
exit(EXIT_SUCCESS);
}

14
test/tests.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef CRUCIBLE_TESTS_H
#define CRUCIBLE_TESTS_H
#undef NDEBUG
#include <iostream>
#define RUN_A_TEST(test) do { \
std::cerr << "Testing " << #test << "..." << std::flush; \
do { test ; } while (0); \
std::cerr << "OK" << std::endl; \
} while (0)
#endif // CRUCIBLE_TESTS_H

1
test/tmp/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*