// -*- mode: c++; c-basic-offset:4 -*- // This file is part of libdap, A C++ implementation of the OPeNDAP Data // Access Protocol. // Copyright (c) 2002,2003 OPeNDAP, Inc. // Author: James Gallagher // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library 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 // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. #include #include #include #include #include //#define DODS_DEBUG #include "DDS.h" #include "ConstraintEvaluator.h" #include "../tests/TestTypeFactory.h" #include "../tests/TestSequence.h" #include "../tests/TestInt32.h" #include "../tests/TestStr.h" #include "GNURegex.h" #include "GetOpt.h" #include "debug.h" static bool debug = false; #undef DBG #define DBG(x) do { if (debug) (x); } while(false); using namespace CppUnit; using namespace std; int test_variable_sleep_interval; // Note: MS VC++ won't tolerate the embedded newlines in strings, hence the \n // is explicit. static const char *s_as_string = "BaseType \\(0x.*\\):\n\ _name: s\n\ _type: Sequence\n\ _dataset: \n\ _read_p: 0\n\ _send_p: 0\n\ _synthesized_p: 0\n\ d_parent: 0.*\n\ d_attr: 0x.*\n\ BaseType \\(0x.*\\):\n\ _name: i1\n\ _type: Int32\n\ _dataset: \n\ _read_p: 0\n\ _send_p: 0\n\ _synthesized_p: 0\n\ d_parent: 0x.*\n\ d_attr: 0x.*\n\ BaseType \\(0x.*\\):\n\ _name: str1\n\ _type: String\n\ _dataset: \n\ _read_p: 0\n\ _send_p: 0\n\ _synthesized_p: 0\n\ d_parent: 0x.*\n\ d_attr: 0x.*\n\ BaseType \\(0x.*\\):\n\ _name: i2\n\ _type: Int32\n\ _dataset: \n\ _read_p: 0\n\ _send_p: 0\n\ _synthesized_p: 0\n\ d_parent: 0x.*\n\ d_attr: 0x.*\n\ \n"; static Regex s_regex(s_as_string); namespace libdap { class SequenceTest: public TestFixture { private: DDS *dds; TestSequence *s, *ss, *ps, *sss, *ts, *tts; public: SequenceTest() { } ~SequenceTest() { } void setUp() { // Set up a simple sequence. Used to test ctor, assigment, et cetera. s = new TestSequence("s"); s->add_var_nocopy(new TestInt32("i1")); s->add_var_nocopy(new TestStr("str1")); s->add_var_nocopy(new TestInt32("i2")); s->set_series_values(true); // Set ss, a two level sequence ss = new TestSequence("ss"); ss->add_var_nocopy(new TestInt32("i1")); ss->set_series_values(true); ps = new TestSequence("child_of_ss"); ps->add_var_nocopy(new TestInt32("i2")); ps->set_series_values(true); ss->add_var_nocopy(ps); // Set up sss, used to test multi-level sequences sss = new TestSequence("sss"); sss->add_var_nocopy(new TestInt32("i1")); ts = new TestSequence("child_of_sss"); ts->add_var_nocopy(new TestStr("str1")); tts = new TestSequence("child_of_child_of_sss"); tts->add_var_nocopy(new TestInt32("i2")); ts->add_var_nocopy(tts); sss->add_var_nocopy(ts); // This has to be here because add_var_nocopy adds // copies of its argument. sss->set_series_values(true); TestTypeFactory ttf; dds = new DDS(&ttf); dds->add_var_nocopy(s); dds->add_var_nocopy(ss); dds->add_var_nocopy(sss); } void tearDown() { delete dds; dds = 0; } bool re_match(Regex &r, const char *s) { int match_position = r.match(s, strlen(s)); DBG(cerr << "match position: " << match_position << " string length: " << (int )strlen(s) << endl); return match_position == (int) strlen(s); } CPPUNIT_TEST_SUITE (SequenceTest); CPPUNIT_TEST (ctor_test); CPPUNIT_TEST (assignment); CPPUNIT_TEST (copy_ctor); #if 0 CPPUNIT_TEST(test_set_leaf_sequence); CPPUNIT_TEST(test_set_leaf_sequence2); CPPUNIT_TEST(test_set_leaf_sequence3); CPPUNIT_TEST(intern_data_for_leaf_test); CPPUNIT_TEST(intern_data_test1); CPPUNIT_TEST(intern_data_test2); CPPUNIT_TEST(intern_data_test3); #endif CPPUNIT_TEST_SUITE_END(); #if 0 // Tests for methods void intern_data_test1() { ConstraintEvaluator ce; s->set_send_p(true); s->set_leaf_sequence(); try { s->intern_data(ce, *dds); // Test the first value in the first four rows BaseType *btp = s->var_value(0, 0); CPPUNIT_ASSERT(btp && dynamic_cast(*btp).value() == 32); btp = s->var_value(1, 0); CPPUNIT_ASSERT(btp && dynamic_cast(*btp).value() == 1024); btp = s->var_value(2, 0); CPPUNIT_ASSERT(btp && dynamic_cast(*btp).value() == 32768); btp = s->var_value(3, 0); CPPUNIT_ASSERT(btp && dynamic_cast(*btp).value() == 1048576); DBG(s->print_val(stdout)); } catch (Error &e) { cerr << e.get_error_message() << endl; CPPUNIT_ASSERT(!"Error in transfer_data_for_leaf_test1()"); } } void intern_data_test2() { ConstraintEvaluator ce; ss->set_send_p(true); ss->set_leaf_sequence(); try { ss->intern_data(ce, *dds); DBG(ss->print_val(stdout)); // Test the first value in the first four rows BaseType *btp = ss->var_value(0, 0); CPPUNIT_ASSERT(btp && dynamic_cast(*btp).value() == 32); btp = ss->var_value(1, 0); CPPUNIT_ASSERT(btp && dynamic_cast(*btp).value() == 1024); btp = ss->var_value(2, 0); CPPUNIT_ASSERT(btp && dynamic_cast(*btp).value() == 32768); btp = ss->var_value(3, 0); CPPUNIT_ASSERT(btp && dynamic_cast(*btp).value() == 1048576); // Look at some values in the inner sequence Sequence *sp = dynamic_cast(ss->var_value(0, 1)); CPPUNIT_ASSERT(sp); btp = sp->var_value(0, 0); CPPUNIT_ASSERT(btp && dynamic_cast(*btp).value() == 32); btp = sp->var_value(1, 0); CPPUNIT_ASSERT(btp && dynamic_cast(*btp).value() == 1024); btp = sp->var_value(2, 0); CPPUNIT_ASSERT(btp && dynamic_cast(*btp).value() == 32768); btp = sp->var_value(3, 0); CPPUNIT_ASSERT(btp && dynamic_cast(*btp).value() == 1048576); sp = dynamic_cast(ss->var_value(3, 1)); CPPUNIT_ASSERT(sp); btp = sp->var_value(0, 0); CPPUNIT_ASSERT(btp && dynamic_cast(*btp).value() == 32); btp = sp->var_value(1, 0); CPPUNIT_ASSERT(btp && dynamic_cast(*btp).value() == 1024); btp = sp->var_value(2, 0); CPPUNIT_ASSERT(btp && dynamic_cast(*btp).value() == 32768); btp = sp->var_value(3, 0); CPPUNIT_ASSERT(btp && dynamic_cast(*btp).value() == 1048576); } catch (Error &e) { cerr << e.get_error_message() << endl; CPPUNIT_ASSERT(!"Error in transfer_data_test2()"); } } void intern_data_test3() { ConstraintEvaluator ce; sss->set_send_p(true); sss->set_leaf_sequence(); try { sss->intern_data(ce, *dds); DBG(sss->print_val_by_rows(stdout, "", true, true)); // Test the first value in the first four rows BaseType *btp = sss->var_value(0, 0); CPPUNIT_ASSERT(btp && dynamic_cast(*btp).value() == 32); btp = sss->var_value(1, 0); CPPUNIT_ASSERT(btp && dynamic_cast(*btp).value() == 1024); btp = sss->var_value(2, 0); CPPUNIT_ASSERT(btp && dynamic_cast(*btp).value() == 32768); btp = sss->var_value(3, 0); CPPUNIT_ASSERT(btp && dynamic_cast(*btp).value() == 1048576); // Look at some values in the inner-most sequence (skip the middle // sequence since I don't have a value() accessor for that yet. Sequence *sp = dynamic_cast(sss->var_value(0, 1)); CPPUNIT_ASSERT(sp); Sequence *ssp = dynamic_cast(sp->var_value(0, 1)); CPPUNIT_ASSERT(ssp); btp = ssp->var_value(0, 0); CPPUNIT_ASSERT(btp && dynamic_cast(*btp).value() == 32); btp = ssp->var_value(1, 0); CPPUNIT_ASSERT(btp && dynamic_cast(*btp).value() == 1024); btp = ssp->var_value(2, 0); CPPUNIT_ASSERT(btp && dynamic_cast(*btp).value() == 32768); btp = ssp->var_value(3, 0); CPPUNIT_ASSERT(btp && dynamic_cast(*btp).value() == 1048576); sp = dynamic_cast(sss->var_value(3, 1)); CPPUNIT_ASSERT(sp); ssp = dynamic_cast(sp->var_value(3, 1)); CPPUNIT_ASSERT(ssp); btp = ssp->var_value(0, 0); CPPUNIT_ASSERT(btp && dynamic_cast(*btp).value() == 32); btp = ssp->var_value(1, 0); CPPUNIT_ASSERT(btp && dynamic_cast(*btp).value() == 1024); btp = ssp->var_value(2, 0); CPPUNIT_ASSERT(btp && dynamic_cast(*btp).value() == 32768); btp = ssp->var_value(3, 0); CPPUNIT_ASSERT(btp && dynamic_cast(*btp).value() == 1048576); } catch (Error &e) { cerr << e.get_error_message() << endl; CPPUNIT_ASSERT(!"Error in transfer_data_test3()"); } } void intern_data_for_leaf_test() { ConstraintEvaluator ce; s->set_send_p(true); try { Sequence::sequence_values_stack_t sequence_values_stack; sequence_values_stack.push(&s->d_values); s->intern_data_for_leaf(*dds, ce, sequence_values_stack); // Test the first value in the first four rows BaseType *btp = s->var_value(0, 0); CPPUNIT_ASSERT(dynamic_cast(*btp).value() == 32); btp = s->var_value(1, 0); CPPUNIT_ASSERT(dynamic_cast(*btp).value() == 1024); btp = s->var_value(2, 0); CPPUNIT_ASSERT(dynamic_cast(*btp).value() == 32768); btp = s->var_value(3, 0); CPPUNIT_ASSERT(dynamic_cast(*btp).value() == 1048576); DBG(s->print_val(stdout)); } catch (Error &e) { cerr << e.get_error_message() << endl; CPPUNIT_ASSERT(!"Error in transfer_data_for_leaf_test()"); } } void test_set_leaf_sequence3() { // Test for the rejection of a Sequence with two sequences in it. sss->add_var_nocopy(ss); sss->set_send_p(true); try { sss->set_leaf_sequence(1); CPPUNIT_ASSERT(!"Should have thrown Error"); } catch (Error &e) { cerr << e.get_error_message() << endl; CPPUNIT_ASSERT("Caught Error"); } } void test_set_leaf_sequence2() { // Three level sequence sss->set_send_p(true);// set send_p for whole seq // Now the lowest sequence is not longer to be sent. The middle sequence // is the lowest with fields to be sent and so should be the leaf. Sequence::Vars_iter i = sss->var_begin(); Sequence *inner = dynamic_cast(*++i); i = inner->var_begin(); inner = dynamic_cast(*++i); inner->set_send_p(false);// now clear send_p for the inner most seq sss->set_leaf_sequence(1); CPPUNIT_ASSERT(!sss->is_leaf_sequence()); i = sss->var_begin(); inner = dynamic_cast(*++i); CPPUNIT_ASSERT(inner && inner->is_leaf_sequence()); i = inner->var_begin(); Sequence *inner2 = dynamic_cast(*++i); CPPUNIT_ASSERT(inner2 && !inner2->is_leaf_sequence()); } void test_set_leaf_sequence() { // One level sequence s->set_send_p(true); s->set_leaf_sequence(1); CPPUNIT_ASSERT(s->is_leaf_sequence()); // Two level sequence ss->set_send_p(true); ss->set_leaf_sequence(1); CPPUNIT_ASSERT(!ss->is_leaf_sequence()); // add_var_nocopy() _copies_ the object, so ps should not be used here. Sequence::Vars_iter i = ss->var_begin(); Sequence *inner = dynamic_cast(*++i); CPPUNIT_ASSERT(inner->type() == dods_sequence_c && inner->is_leaf_sequence()); // Three level sequence sss->set_send_p(true); sss->set_leaf_sequence(1); CPPUNIT_ASSERT(!sss->is_leaf_sequence()); i = sss->var_begin(); inner = dynamic_cast(*++i); CPPUNIT_ASSERT(inner && !inner->is_leaf_sequence()); i = inner->var_begin(); Sequence *inner2 = dynamic_cast(*++i); CPPUNIT_ASSERT(inner2 && inner2->is_leaf_sequence()); } #endif void assignment() { Sequence ts2 = *s; DBG(cerr << "ts2: " << ts2.toString() << endl); CPPUNIT_ASSERT(re_match(s_regex, ts2.toString().c_str())); } void ctor_test() { DBG(cerr << "s: " << s->toString() << endl); CPPUNIT_ASSERT(re_match(s_regex, s->toString().c_str())); } void copy_ctor() { Sequence s2 = *s; CPPUNIT_ASSERT(re_match(s_regex, s2.toString().c_str())); } }; CPPUNIT_TEST_SUITE_REGISTRATION (SequenceTest); } int main(int argc, char*argv[]) { GetOpt getopt(argc, argv, "dh"); int option_char; while ((option_char = getopt()) != -1) switch (option_char) { case 'd': debug = 1; // debug is a static global break; case 'h': { // help - show test names cerr << "Usage: SequenceTest has the following tests:" << endl; const std::vector &tests = libdap::SequenceTest::suite()->getTests(); unsigned int prefix_len = libdap::SequenceTest::suite()->getName().append("::").length(); for (std::vector::const_iterator i = tests.begin(), e = tests.end(); i != e; ++i) { cerr << (*i)->getName().replace(0, prefix_len, "") << endl; } break; } default: break; } CppUnit::TextTestRunner runner; runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest()); bool wasSuccessful = true; string test = ""; int i = getopt.optind; if (i == argc) { // run them all wasSuccessful = runner.run(""); } else { for (; i < argc; ++i) { if (debug) cerr << "Running " << argv[i] << endl; test = libdap::SequenceTest::suite()->getName().append("::").append(argv[i]); wasSuccessful = wasSuccessful && runner.run(test); } } return wasSuccessful ? 0 : 1; }