Main Page | Namespace List | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Namespace Members | Data Fields | Globals
reflect » test

reflect/test/unit_test.cpp

Go to the documentation of this file.
00001 //
00002 // Copyright (c) 2003
00003 // Paul Hamilton; pHamtec P/L
00004 //
00005 // Permission to use, copy, modify, distribute and sell this software
00006 // and its documentation for any purpose is hereby granted without fee, 
00007 // provided that the above copyright notice appears in all copies and 
00008 // that both the copyright notice and this permission notice appear in 
00009 // supporting documentation. No representations are made about the 
00010 // suitability of this software for any purpose. It is provided "as is" 
00011 // without express or implied warranty.
00012 //
00013 // unit_test.cpp
00014 //
00015 // 4-Jul-2003 phamilton Created
00016 //
00017 
00018 #include <iostream>
00019 #include <vector>
00020 #include <string>
00021 #include <boost/test/included/unit_test_framework.hpp>
00022 #include "../object_visitor.hpp"
00023 #include "../jscript_object_navigator.hpp"
00024 #include "../jscript_object_nav_errors.h"
00025 #include "../member_visitor.hpp"
00026 #include "root.hpp"
00027 #include "foo.hpp"
00028 #include "bar.hpp"
00029 
00030 using namespace ph::reflect;
00031 using namespace reflect_test;
00032 using boost::unit_test_framework::test_suite;
00033 using boost::test_toolbox::output_test_stream;
00034 
00035 static void set(base *obj, const std::string &name, const std::string &val)
00036 {
00037 set_member_visitor v(name, val);
00038 obj->accept(&v);
00039 }
00040 
00041 static std::string get(base *obj, const std::string &name)
00042 {
00043 ph::common::get_member_value_visitor v(name);
00044 obj->accept(&v);
00045 return v.get();
00046 }
00047 
00048 // here are some macros we use to test whether an object with a particular path has the correct name.
00049 // they are macros so that they will display the correct line number.
00050 
00051 #define TEST_OBJ_NAME(_obj_, _path_, _name_) \
00052 { \
00053  ph::common::object_base *o = nav.navigate(_obj_, _path_); \
00054  BOOST_CHECK(output.is_empty()); \
00055  BOOST_REQUIRE_MESSAGE(o, "could not find [" _path_ "]"); \
00056  std::string name; \
00057  BOOST_CHECK_MESSAGE(ph::common::get_visitable_obj_name(o, &name), \
00058  "[" _path_ "] object does not have a name."); \
00059  BOOST_CHECK_MESSAGE(name == _name_, \
00060  "[" _path_ "] was named [" + name + "] not [" _name_ "]"); \
00061 }
00062 
00063 #define TEST_BAD_PARSE(_obj_, _path_, _msg_, _name_) \
00064 { \
00065  BOOST_CHECK(nav.navigate(_obj_, _path_) == 0); \
00066  BOOST_CHECK_MESSAGE(output.is_equal( \
00067  "Syntax Error. " _msg_ " [" _name_ "]\n"), "Syntax Error. " _msg_ " [" _name_ "]"); \
00068 }
00069 
00070 namespace reflect_test {
00071 
00072 class test_simple
00073 {
00074 public:
00075 void test()
00076 {
00077 foo *o = new foo("foo", "foo");
00078 BOOST_REQUIRE_MESSAGE(o, "could not create foo object.");
00079 set(o, "x", "1");
00080 set(o, "y", "2.1");
00081 set(o, "z", "true");
00082 BOOST_CHECK(get(o, "x") == "1");
00083 BOOST_CHECK(get(o, "y") == "2.1");
00084 BOOST_CHECK(get(o, "z") == "true");
00085 delete o;
00086 }
00087 };
00088 
00089 class test_composite
00090 {
00091 public:
00092 
00093 void test()
00094 {
00095 {
00096 // create a root object.
00097 root *r = new root("root", "root");
00098 
00099 // now search for a particular object using the object parser.
00100 output_test_stream output;
00101 jscript_object_navigator nav(r, &output, false, false);
00102 
00103 // test adding new members to the composites.
00104 ph::common::object_base *p = nav.navigate(r, "root().foos()");
00105 BOOST_CHECK(output.is_empty());
00106 BOOST_REQUIRE(p);
00107 BOOST_REQUIRE_MESSAGE(p->composition(), 
00108 "object does not implement composite interface.");
00109 ph::common::composite_object_base *c = 
00110 p->composition()->composite();
00111 BOOST_REQUIRE_MESSAGE(c, "foos was not a composite object.");
00112 
00113 // create a new foo object.
00114 foo *foo_1 = new foo("foo", "foo_1");
00115 BOOST_REQUIRE_MESSAGE(foo_1, "could not create foo object.");
00116 BOOST_CHECK(c->add(foo_1, true));
00117 
00118 // make sure it's there.
00119 TEST_OBJ_NAME(r, "root().foos(1)", "foo_1");
00120 
00121 // now remove it.
00122 BOOST_CHECK(c->remove(foo_1));
00123 
00124 // make sure it's not there.
00125 TEST_BAD_PARSE(r, "root().foos(1)", 
00126 "Object with numeric subscript was not found.", "1");
00127 
00128 // test the singleton composite to make sure that errors working.
00129 TEST_BAD_PARSE(r, "root().a_foo", "Singleton composite was empty.", "a_foo");
00130 
00131 // now add foo onto the a_foo
00132 p = nav.navigate(r, "root().a_foo()");
00133 BOOST_CHECK(output.is_empty());
00134 BOOST_REQUIRE(p);
00135 BOOST_REQUIRE_MESSAGE(p->composition(), 
00136 "object does not implement composite interface.");
00137 c = p->composition()->composite();
00138 BOOST_REQUIRE_MESSAGE(c, "object was not a composite object.");
00139 
00140 BOOST_CHECK(c->add(foo_1, true));
00141 
00142 // make sure it's there.
00143 TEST_OBJ_NAME(r, "root().a_foo", "foo_1");
00144 
00145 delete r;
00146 }
00147 {
00148 // create a root object.
00149 root *r = new root("root", "root");
00150 
00151 // now search for a particular object using the object parser.
00152 output_test_stream output;
00153 jscript_object_navigator nav(r, &output, false);
00154 
00155 // now add a bunch of foos and bars to this object.
00156 r->addfoosandbars();
00157 
00158 // test the parent-relationship of composites.
00159 ph::common::object_base *bar_2 = nav.navigate(r, "root().bars('bar_2')");
00160 BOOST_CHECK(output.is_empty());
00161 BOOST_CHECK(bar_2);
00162 if (bar_2)
00163 {
00164 // get bars
00165 ph::common::object_base *bars = nav.navigate(r, "root().bars()");
00166 BOOST_CHECK(output.is_empty());
00167 BOOST_CHECK(bars);
00168 if (bars)
00169 test_parents(bar_2, bars, "bars");
00170 }
00171 
00172 // test the parent-relationship of references.
00173 ph::common::object_base *foo_3 = nav.navigate(r, "root().a_foo");
00174 BOOST_CHECK(output.is_empty());
00175 BOOST_CHECK(foo_3);
00176 if (foo_3)
00177 {
00178 // get a_foo
00179 ph::common::object_base *a_foo = nav.navigate(r, "root().a_foo()");
00180 BOOST_CHECK(output.is_empty());
00181 BOOST_CHECK(a_foo);
00182 if (a_foo)
00183 test_parents(foo_3, a_foo, "a_foo");
00184 }
00185 
00186 delete r;
00187 }
00188 }
00189 
00190 void test_parents(ph::common::object_base *obj, 
00191 ph::common::object_base *composite, const std::string &parentname)
00192 /*
00193  test the parent-relationship of composites.
00194  */
00195 {
00196 // see what the name of the parent of this guy is.
00197 BOOST_REQUIRE_MESSAGE(obj->outerable(), 
00198 "object doesn't implement outer interface.");
00199 ph::common::object_base *parent = obj->outerable()->outer();
00200 BOOST_CHECK(parent);
00201 if (parent)
00202 {
00203 // test comparable interface.
00204 BOOST_REQUIRE_MESSAGE(parent->comparable(), 
00205 "parent doesn't implement comparable interface");
00206 BOOST_CHECK(parent->comparable()->equal(composite));
00207 
00208 // now walk out and make sure all the parents are correct.
00209 std::string name;
00210 BOOST_CHECK_MESSAGE(ph::common::get_visitable_obj_name(parent, &name),
00211 "object does not have a name.");
00212 BOOST_CHECK(name == parentname);
00213 BOOST_REQUIRE_MESSAGE(parent->outerable(), 
00214 "parent doesn't implement outer interface.");
00215 parent = parent->outerable()->outer();
00216 BOOST_CHECK(parent);
00217 if (parent)
00218 {
00219 BOOST_CHECK_MESSAGE(ph::common::get_visitable_obj_name(parent, &name),
00220 "object does not have a name.");
00221 BOOST_CHECK(name == "root");
00222 BOOST_REQUIRE_MESSAGE(parent->outerable(), 
00223 "parent doesn't implement outer interface.");
00224 BOOST_CHECK(parent->outerable()->outer() == 0);
00225 }
00226 }
00227 }
00228 };
00229 
00230 class test_navigation
00231 {
00232 public:
00233 
00234 void test()
00235 {
00236 // create a root object.
00237 root *r = new root("root", "root");
00238 
00239 // now add a bunch of foos and bars to this object.
00240 r->addfoosandbars();
00241 
00242 // now search for a particular object using the object parser.
00243 output_test_stream output;
00244 jscript_object_navigator nav(r, &output, false, false);
00245 
00246 // test root() navigation.
00247 TEST_OBJ_NAME(r, "root()", "root");
00248 
00249 // test sub-object navigation.
00250 TEST_OBJ_NAME(r, "root().foos('foo_2')", "foo_2");
00251 TEST_OBJ_NAME(r, "root().foos(1)", "foo_1");
00252 TEST_OBJ_NAME(r, "root().foos(2)", "foo_2");
00253 TEST_OBJ_NAME(r, "root().bars('bar_1')", "bar_1");
00254 TEST_OBJ_NAME(r, "root().bars(1)", "bar_1");
00255 TEST_OBJ_NAME(r, "root().bars(2)", "bar_2");
00256 
00257 // test for invalid composites.
00258 TEST_BAD_PARSE(r, "root().foos", 
00259 "Object was not a singleton composite. Did you mean to use ()?.", "foos");
00260 
00261 // test composite navigation.
00262 TEST_OBJ_NAME(r, "root().foos()", "foos");
00263 TEST_OBJ_NAME(r, "root().a_foo()", "a_foo");
00264 
00265 // test for our object reference special case. 
00266 // The name of the composite actually returns the 
00267 // object attached.
00268 TEST_OBJ_NAME(r, "root().a_foo", "foo_3");
00269 
00270 // test complicated queries.
00271 TEST_OBJ_NAME(r, "root().foos('foo_2').parent().bars('bar_1')", "bar_1");
00272 
00273 // test for gobbledegook.
00274 
00275 // no composites.
00276 TEST_BAD_PARSE(r, "()", "No builtin or composite found.", "");
00277 TEST_BAD_PARSE(r, "xxxxx()", "No builtin or composite found.", "xxxxx");
00278 TEST_BAD_PARSE(r, "root().xxxxx()", "No builtin or composite found.", "xxxxx");
00279 TEST_BAD_PARSE(r, "root().()", "No builtin or composite found.", "");
00280 
00281 TEST_BAD_PARSE(r, "yyyy(1)", "No composite found.", "yyyy");
00282 
00283 TEST_BAD_PARSE(r, "root().foos(1).parent('xxxx')", "Parent was not found.", "xxxx");
00284 TEST_BAD_PARSE(r, "root().foos(1).parent(2)", 
00285 "Parent with subscript was not found.", "2");
00286 
00287 TEST_BAD_PARSE(r, "root().foos(5)", 
00288 "Object with numeric subscript was not found.", "5");
00289 
00290 TEST_BAD_PARSE(r, "root().foos('xxxx')", 
00291 "Object with name subscript was not found.", "'xxxx'");
00292 
00293 // couldn't find objects.
00294 TEST_BAD_PARSE(r, "xxxxx", "No composite found.", "xxxxx");
00295 TEST_BAD_PARSE(r, "root().xxxxx", "No composite found.", "xxxxx");
00296 TEST_BAD_PARSE(r, "root().foos('foo_1", "No composite found.", "foos('foo_1");
00297 TEST_BAD_PARSE(r, "root().foos('foo_1'", "No composite found.", "foos('foo_1'");
00298 TEST_BAD_PARSE(r, "root().foos('", "No composite found.", "foos('");
00299 TEST_BAD_PARSE(r, "root().foos(", "No composite found.", "foos(");
00300 TEST_BAD_PARSE(r, "root(", "No composite found.", "root(");
00301 
00302 // couldn't parse.
00303 TEST_BAD_PARSE(r, "....", "Empty part. Couldn't Parse.", "....");
00304 
00305 delete r;
00306 }
00307 };
00308 
00309 class test_dump
00310 {
00311 public:
00312 test_dump(const std::string &filename) :
00313 _filename(filename)
00314 {};
00315 
00316 void test()
00317 {
00318 // create a root object.
00319 root *r = new root("root", "root");
00320 
00321 // now add a bunch of foos and bars to this object.
00322 r->addfoosandbars();
00323 
00324 {
00325 output_test_stream output(_filename, true);
00326 {
00327 dump_object_visitor v(&output);
00328 BOOST_CHECK(r->accept(&v));
00329 }
00330 BOOST_CHECK(output.match_pattern());
00331 }
00332 
00333 delete r;
00334 }
00335 
00336 private:
00337 std::string _filename;
00338 };
00339 
00340 };
00341 
00342 test_suite *init_unit_test_suite(int argc, char* argv[]) 
00343 {
00344 test_suite * test = BOOST_TEST_SUITE("reflect units tests");
00345 
00346 test->add(BOOST_CLASS_TEST_CASE(&test_simple::test, 
00347 boost::shared_ptr<test_simple>(new test_simple())));
00348 test->add(BOOST_CLASS_TEST_CASE(&test_composite::test, 
00349 boost::shared_ptr<test_composite>(new test_composite()))); 
00350 test->add(BOOST_CLASS_TEST_CASE(&test_navigation::test, 
00351 boost::shared_ptr<test_navigation>(new test_navigation())));
00352 test->add(BOOST_CLASS_TEST_CASE(&test_dump::test, 
00353 boost::shared_ptr<test_dump>(new test_dump(argv[1]))));
00354 
00355 return test;
00356 }

Generated on Wed Apr 5 22:03:26 2006 for cppxmlobj by doxygen 1.4.3

AltStyle によって変換されたページ (->オリジナル) /