=== modified file 'Makefile'
@@ -1,24 +1,31 @@
-TARGETS = libmatrix.a
-TESTS = matrix_inverse_test
-SRCS = mat.cc program.cc matrix_inverse_test.cc
-OBJS = $(SRCS:.cc=.o)
CXXFLAGS = -Wall -Werror -pedantic -O3
+LIBMATRIX = libmatrix.a
+LIBSRCS = mat.cc program.cc
+LIBOBJS = $(LIBSRCS:.cc=.o)
+TESTDIR = test
+LIBMATRIX_TESTS = $(TESTDIR)/libmatrix_test
+TESTSRCS = $(TESTDIR)/options.cc \
+ $(TESTDIR)/inverse_test.cc \
+ $(TESTDIR)/libmatrix_test.cc
+TESTOBJS = $(TESTSRCS:.cc=.o)
# Make sure to build both the library targets and the tests, and generate
# a make failure if the tests don't pass.
-default: $(TARGETS) $(TESTS) run_tests
+default: $(LIBMATRIX) $(LIBMATRIX_TESTS) run_tests
# Main library targets here.
-mat.o : mat.cc mat.h
-program.o: program.cc program.h
+mat.o : mat.cc mat.h vec.h
+program.o: program.cc program.h mat.h vec.h
libmatrix.a : mat.o mat.h stack.h vec.h program.o program.h
- $(AR) -r $@ $(OBJS)
+ $(AR) -r $@ $(LIBOBJS)
# Tests and execution targets here.
-matrix_inverse_test.o: matrix_inverse_test.cc mat.h
-matrix_inverse_test: matrix_inverse_test.o libmatrix.a
+$(TESTDIR)/options.o: $(TESTDIR)/options.cc $(TESTDIR)/libmatrix_test.h
+$(TESTDIR)/libmatrix_test.o: $(TESTDIR)/libmatrix_test.cc $(TESTDIR)/libmatrix_test.h $(TESTDIR)/inverse_test.h
+$(TESTDIR)/inverse_test.o: $(TESTDIR)/inverse_test.cc $(TESTDIR)/inverse_test.h $(TESTDIR)/libmatrix_test.h mat.h
+$(TESTDIR)/libmatrix_test: $(TESTDIR)/options.o $(TESTDIR)/libmatrix_test.o $(TESTDIR)/inverse_test.o libmatrix.a
$(CXX) -o $@ $?
-run_tests: $(TESTS)
- ./matrix_inverse_test
+run_tests: $(LIBMATRIX_TESTS)
+ $(LIBMATRIX_TESTS)
clean :
- $(RM) $(OBJS) $(TARGETS)
+ $(RM) $(LIBOBJS) $(TESTOBJS) $(LIBMATRIX) $(LIBMATRIX_TESTS)
=== added directory 'test'
=== added file 'test/inverse_test.cc'
@@ -0,0 +1,161 @@
+#include <iostream>
+#include "libmatrix_test.h"
+#include "inverse_test.h"
+#include "../mat.h"
+
+using LibMatrix::mat2;
+using LibMatrix::mat3;
+using LibMatrix::mat4;
+using std::cout;
+using std::endl;
+
+void
+MatrixTest2x2Inverse::run(const Options& options)
+{
+ mat2 m;
+
+ if (options.beVerbose())
+ {
+ cout << "Starting with mat2 (should be identity): " << endl << endl;
+ m.print();
+ }
+
+ m[0][1] = -2.5;
+
+ if (options.beVerbose())
+ {
+ cout << endl << "Matrix should now have (0, 1) == -2.500000" << endl << endl;
+ m.print();
+ }
+
+ mat2 mi(m);
+
+ if (options.beVerbose())
+ {
+ cout << endl << "Copy of previous matrix (should have (0, 1) == -2.500000)" << endl << endl;
+ mi.print();
+ }
+
+ mi.inverse();
+
+ if (options.beVerbose())
+ {
+ cout << endl << "Inverse of copy: " << endl << endl;
+ mi.print();
+ }
+
+ mat2 i = m * mi;
+
+ if (options.beVerbose())
+ {
+ cout << endl << "Product of original and inverse (should be identity): " << endl << endl;
+ i.print();
+ }
+
+ mat2 ident;
+ if (i == ident)
+ {
+ pass_ = true;
+ }
+}
+
+void
+MatrixTest3x3Inverse::run(const Options& options)
+{
+ mat3 m;
+
+ if (options.beVerbose())
+ {
+ cout << "Starting with mat3 (should be identity): " << endl << endl;
+ m.print();
+ }
+
+ m[1][2] = -2.5;
+
+ if (options.beVerbose())
+ {
+ cout << endl << "Matrix should now have (1, 2) == -2.500000" << endl << endl;
+ m.print();
+ }
+
+ mat3 mi(m);
+
+ if (options.beVerbose())
+ {
+ cout << endl << "Copy of previous matrix (should have (1, 2) == -2.500000)" << endl << endl;
+ mi.print();
+ }
+
+ mi.inverse();
+
+ if (options.beVerbose())
+ {
+ cout << endl << "Inverse of copy: " << endl << endl;
+ mi.print();
+ }
+
+ mat3 i = m * mi;
+
+ if (options.beVerbose())
+ {
+ cout << endl << "Product of original and inverse (should be identity): " << endl << endl;
+ i.print();
+ }
+
+ mat3 ident;
+ if (i == ident)
+ {
+ pass_ = true;
+ }
+}
+
+void
+MatrixTest4x4Inverse::run(const Options& options)
+{
+ mat4 m;
+
+ if (options.beVerbose())
+ {
+ cout << "Starting with mat4 (should be identity): " << endl << endl;
+ m.print();
+ }
+
+ m[2][3] = -2.5;
+
+ if (options.beVerbose())
+ {
+ cout << endl << "Matrix should now have (2, 3) == -2.500000" << endl << endl;
+ m.print();
+ }
+
+ mat4 mi(m);
+
+ if (options.beVerbose())
+ {
+ cout << endl << "Copy of previous matrix (should have (2, 3) == -2.500000)" << endl << endl;
+ mi.print();
+ }
+
+ mi.inverse();
+
+ if (options.beVerbose())
+ {
+ cout << endl << "Inverse of copy: " << endl << endl;
+ mi.print();
+ }
+
+ mat4 i = m * mi;
+
+ if (options.beVerbose())
+ {
+ cout << endl << "Product of original and inverse (should be identity): " << endl << endl;
+ i.print();
+ }
+
+ mat4 ident;
+ if (i == ident)
+ {
+ pass_ = true;
+ }
+}
+
=== added file 'test/inverse_test.h'
@@ -0,0 +1,28 @@
+#ifndef INVERSE_TEST_H_
+#define INVERSE_TEST_H_
+
+class MatrixTest;
+class Options;
+
+class MatrixTest2x2Inverse : public MatrixTest
+{
+public:
+ MatrixTest2x2Inverse() : MatrixTest("mat2::inverse") {}
+ virtual void run(const Options& options);
+};
+
+class MatrixTest3x3Inverse : public MatrixTest
+{
+public:
+ MatrixTest3x3Inverse() : MatrixTest("mat3::inverse") {}
+ virtual void run(const Options& options);
+};
+
+class MatrixTest4x4Inverse : public MatrixTest
+{
+public:
+ MatrixTest4x4Inverse() : MatrixTest("mat4::inverse") {}
+ virtual void run(const Options& options);
+};
+
+#endif // INVERSE_TEST_H_
=== renamed file 'matrix_inverse_test.cc' => 'test/libmatrix_test.cc'
@@ -10,143 +10,48 @@
// Jesse Barker - original implementation.
//
#include <iostream>
-#include "mat.h"
+#include <string>
+#include <vector>
+#include "libmatrix_test.h"
+#include "inverse_test.h"
-using LibMatrix::mat4;
-using LibMatrix::mat3;
-using LibMatrix::mat2;
using std::cerr;
using std::cout;
using std::endl;
-bool mat2OK()
-{
- mat2 m;
- cout << "Starting with mat2 (should be identity): " << endl << endl;
- m.print();
-
- m[0][1] = -2.5;
-
- cout << endl << "Matrix should now have (0, 1) == -2.500000" << endl << endl;
- m.print();
-
- mat2 mi(m);
-
- cout << endl << "Copy of previous matrix (should have (0, 1) == -2.500000)" << endl << endl;
- mi.print();
-
- mi.inverse();
-
- cout << endl << "Inverse of copy: " << endl << endl;
- mi.print();
-
- mat2 i = m * mi;
-
- cout << endl << "Product of original and inverse (should be identity): " << endl << endl;
- i.print();
-
- mat2 ident;
- if (i != ident)
- {
- return false;
- }
-
- return true;
-}
-
-bool mat3OK()
-{
- mat3 m;
- cout << "Starting with mat3 (should be identity): " << endl << endl;
- m.print();
-
- m[1][2] = -2.5;
-
- cout << endl << "Matrix should now have (1, 2) == -2.500000" << endl << endl;
- m.print();
-
- mat3 mi(m);
-
- cout << endl << "Copy of previous matrix (should have (1, 2) == -2.500000)" << endl << endl;
- mi.print();
-
- mi.inverse();
-
- cout << endl << "Inverse of copy: " << endl << endl;
- mi.print();
-
- mat3 i = m * mi;
-
- cout << endl << "Product of original and inverse (should be identity): " << endl << endl;
- i.print();
-
- mat3 ident;
- if (i != ident)
- {
- return false;
- }
-
- return true;
-}
-
-bool mat4OK()
-{
- mat4 m;
- cout << "Starting with mat4 (should be identity): " << endl << endl;
- m.print();
-
- m[2][3] = -2.5;
-
- cout << endl << "Matrix should now have (2, 3) == -2.500000" << endl << endl;
- m.print();
-
- mat4 mi(m);
-
- cout << endl << "Copy of previous matrix (should have (2, 3) == -2.500000)" << endl << endl;
- mi.print();
-
- mi.inverse();
-
- cout << endl << "Inverse of copy: " << endl << endl;
- mi.print();
-
- mat4 i = m * mi;
-
- cout << endl << "Product of original and inverse (should be identity): " << endl << endl;
- i.print();
-
- mat4 ident;
- if (i != ident)
- {
- return false;
- }
-
- return true;
-}
-
int
main(int argc, char** argv)
{
- if (!mat2OK())
- {
- cerr << "mat2::inverse() does not work!" << endl;
- return 1;
- }
- cout << "mat2::inverse() is okay!" << endl << endl;
-
- if (!mat3OK())
- {
- cerr << "mat3::inverse() does not work!" << endl;
- return 1;
- }
- cout << "mat3::inverse() is okay!" << endl << endl;
-
- if (!mat4OK())
- {
- cerr << "mat4::inverse() does not work!" << endl;
- return 1;
- }
- cout << "mat4::inverse() is okay!" << endl << endl;
+ Options testOptions("matrix_test");
+ testOptions.parseArgs(argc, argv);
+ if (testOptions.showHelp())
+ {
+ testOptions.printUsage();
+ return 0;
+ }
+
+ using std::vector;
+ vector<MatrixTest*> testVec;
+ testVec.push_back(new MatrixTest2x2Inverse());
+ testVec.push_back(new MatrixTest3x3Inverse());
+ testVec.push_back(new MatrixTest4x4Inverse());
+
+ for (vector<MatrixTest*>::iterator testIt = testVec.begin();
+ testIt != testVec.end();
+ testIt++)
+ {
+ MatrixTest* curTest = *testIt;
+ curTest->run(testOptions);
+ if (!curTest->passed())
+ {
+ cerr << curTest->name() << " does not work!" << endl;
+ return 1;
+ }
+ if (testOptions.beVerbose())
+ {
+ cout << curTest->name() << " is okay!" << endl;
+ }
+ }
return 0;
}
=== added file 'test/libmatrix_test.h'
@@ -0,0 +1,40 @@
+#ifndef LIBMATRIX_TEST_H_
+#define LIBMATRIX_TEST_H_
+
+class Options
+{
+ Options();
+ static const std::string verbose_name_;
+ static const std::string help_name_;
+ std::string app_name_;
+ bool show_help_;
+ bool verbose_;
+public:
+ Options(const std::string& app_name) :
+ app_name_(app_name),
+ show_help_(false),
+ verbose_(false) {}
+ ~Options() {}
+ bool beVerbose() const { return verbose_; }
+ bool showHelp() const { return show_help_; }
+ void parseArgs(int argc, char** argv);
+ void printUsage();
+};
+
+class MatrixTest
+{
+ std::string name_;
+protected:
+ bool pass_;
+ MatrixTest();
+public:
+ MatrixTest(const std::string& name) :
+ name_(name),
+ pass_(false) {}
+ ~MatrixTest();
+ const std::string& name() const { return name_; }
+ virtual void run(const Options& options) = 0;
+ const bool passed() const { return pass_; }
+};
+
+#endif // LIBMATRIX_TEST_H_
=== added file 'test/options.cc'
@@ -0,0 +1,56 @@
+#include <iostream>
+#include <iomanip>
+#include <getopt.h>
+#include "libmatrix_test.h"
+
+using std::cout;
+using std::endl;
+
+const std::string Options::verbose_name_("verbose");
+const std::string Options::help_name_("help");
+
+void
+Options::parseArgs(int argc, char** argv)
+{
+ static struct option long_options[] = {
+ {"verbose", 0, 0, 0},
+ {"help", 0, 0, 0},
+ {0, 0, 0, 0}
+ };
+ int option_index(0);
+ int c = getopt_long(argc, argv, "", long_options, &option_index);
+ while (c != -1)
+ {
+ std::string optname(long_options[option_index].name);
+
+ if (optname == verbose_name_)
+ {
+ verbose_ = true;
+ }
+ else if (optname == help_name_)
+ {
+ show_help_ = true;
+ }
+ c = getopt_long(argc, argv, "",
+ long_options, &option_index);
+ }
+}
+
+
+static void
+emitColumnOne(const std::string& text)
+{
+ cout << std::setw(16) << text;
+}
+
+void
+Options::printUsage()
+{
+ cout << app_name_ << ": directed functional test utility for libmatrix." << endl;
+ cout << "Options:" << endl;
+ emitColumnOne("--verbose");
+ cout << std::setw(0) << " Enable verbose output during test runs." << endl;
+ emitColumnOne("--help");
+ cout << std::setw(0) << " Print this usage text." << endl;
+}
+