Blame tests/expr-test.cc

Packit a4aae4
Packit a4aae4
// -*- mode: c++; c-basic-offset:4 -*-
Packit a4aae4
Packit a4aae4
// This file is part of libdap, A C++ implementation of the OPeNDAP Data
Packit a4aae4
// Access Protocol.
Packit a4aae4
Packit a4aae4
// Copyright (c) 2002,2003 OPeNDAP, Inc.
Packit a4aae4
// Author: James Gallagher <jgallagher@opendap.org>
Packit a4aae4
//
Packit a4aae4
// This library is free software; you can redistribute it and/or
Packit a4aae4
// modify it under the terms of the GNU Lesser General Public
Packit a4aae4
// License as published by the Free Software Foundation; either
Packit a4aae4
// version 2.1 of the License, or (at your option) any later version.
Packit a4aae4
//
Packit a4aae4
// This library is distributed in the hope that it will be useful,
Packit a4aae4
// but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit a4aae4
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit a4aae4
// Lesser General Public License for more details.
Packit a4aae4
//
Packit a4aae4
// You should have received a copy of the GNU Lesser General Public
Packit a4aae4
// License along with this library; if not, write to the Free Software
Packit a4aae4
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
Packit a4aae4
//
Packit a4aae4
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
Packit a4aae4
Packit a4aae4
// (c) COPYRIGHT URI/MIT 1995-1999
Packit a4aae4
// Please read the full copyright statement in the file COPYRIGHT_URI.
Packit a4aae4
//
Packit a4aae4
// Authors:
Packit a4aae4
//      jhrg,jimg       James Gallagher <jgallagher@gso.uri.edu>
Packit a4aae4
Packit a4aae4
// Test the CE scanner and parser.
Packit a4aae4
//
Packit a4aae4
// jhrg 9/12/95
Packit a4aae4
Packit a4aae4
#include "config.h"
Packit a4aae4
Packit a4aae4
//#define DODS_DEBUG
Packit a4aae4
Packit a4aae4
#include <stdio.h>
Packit a4aae4
#include <stdlib.h>
Packit a4aae4
#ifdef HAVE_UNISTD_H
Packit a4aae4
#include <unistd.h>
Packit a4aae4
#endif
Packit a4aae4
#include <string.h>
Packit a4aae4
#include <errno.h>
Packit a4aae4
Packit a4aae4
#include <iostream>
Packit a4aae4
#include <fstream>
Packit a4aae4
#include <string>
Packit a4aae4
Packit a4aae4
#include "GetOpt.h"
Packit a4aae4
Packit a4aae4
#include "BaseType.h"
Packit a4aae4
#include "DDS.h"
Packit a4aae4
#include "DataDDS.h"
Packit a4aae4
#include "ConstraintEvaluator.h"
Packit a4aae4
#include "ServerFunctionsList.h"
Packit a4aae4
// #include "XDRStreamUnMarshaller.h"
Packit a4aae4
#include "XDRStreamMarshaller.h"
Packit a4aae4
#include "ResponseBuilder.h"
Packit a4aae4
#include "Response.h"
Packit a4aae4
#include "Connect.h"
Packit a4aae4
#include "Error.h"
Packit a4aae4
Packit a4aae4
#include "TestSequence.h"
Packit a4aae4
#include "TestCommon.h"
Packit a4aae4
#include "TestTypeFactory.h"
Packit a4aae4
Packit a4aae4
#include "TestFunction.h"
Packit a4aae4
Packit a4aae4
#include "parser.h"
Packit a4aae4
#include "expr.h"
Packit a4aae4
#include "ce_expr.tab.hh"
Packit a4aae4
#include "util.h"
Packit a4aae4
Packit a4aae4
#include "debug.h"
Packit a4aae4
Packit a4aae4
using namespace std;
Packit a4aae4
Packit a4aae4
int test_variable_sleep_interval = 0;   // Used in Test* classes for testing
Packit a4aae4
                                      // timeouts.
Packit a4aae4
Packit a4aae4
#define CRLF "\r\n"             // Change this here and in mime_util.cc
Packit a4aae4
#define DODS_DDS_PRX "dods_dds"
Packit a4aae4
#define YY_BUFFER_STATE (void *)
Packit a4aae4
Packit a4aae4
void test_scanner(const string & str);
Packit a4aae4
void test_scanner(bool show_prompt);
Packit a4aae4
void test_parser(ConstraintEvaluator & eval, DDS & table,
Packit a4aae4
                 const string & dds_name, string constraint);
Packit a4aae4
bool read_table(DDS & table, const string & name, bool print);
Packit a4aae4
void evaluate_dds(DDS & table, bool print_constrained, bool xml_syntax);
Packit a4aae4
void constrained_trans(const string & dds_name, const bool constraint_expr,
Packit a4aae4
                       const string & ce, const bool series_values);
Packit a4aae4
void intern_data_test(const string & dds_name, const bool constraint_expr,
Packit a4aae4
                 const string & ce, const bool series_values);
Packit a4aae4
Packit a4aae4
int ce_exprlex();               // exprlex() uses the global ce_exprlval
Packit a4aae4
// int ce_exprparse(void *arg);
Packit a4aae4
void ce_exprrestart(FILE * in);
Packit a4aae4
Packit a4aae4
// Glue routines declared in expr.lex
Packit a4aae4
void ce_expr_switch_to_buffer(void *new_buffer);
Packit a4aae4
void ce_expr_delete_buffer(void *buffer);
Packit a4aae4
void *ce_expr_string(const char *yy_str);
Packit a4aae4
Packit a4aae4
extern int ce_exprdebug;
Packit a4aae4
Packit a4aae4
#if 0
Packit a4aae4
static int keep_temps = 0;      // MT-safe; test code.
Packit a4aae4
#endif
Packit a4aae4
Packit a4aae4
const string version = "version 1.12";
Packit a4aae4
const string prompt = "expr-test: ";
Packit a4aae4
const string options = "sS:bdecvp:w:W:f:k:vx?";
Packit a4aae4
const string usage = "\
Packit a4aae4
\nexpr-test [-s [-S string] -d -c -v [-p dds-file]\
Packit a4aae4
\n[-e expr] [-w|-W dds-file] [-f data-file] [-k expr]]\
Packit a4aae4
\nTest the expression evaluation software.\
Packit a4aae4
\nOptions:\
Packit a4aae4
\n  -s: Feed the input stream directly into the expression scanner, does\
Packit a4aae4
\n      not parse.\
Packit a4aae4
\n  -S: <string> Scan the string as if it was standard input.\
Packit a4aae4
\n  -d: Turn on expression parser debugging.\
Packit a4aae4
\n  -c: Print the constrained DDS (the one that will be returned\
Packit a4aae4
\n      prepended to a data transmission. Must also supply -p and -e \
Packit a4aae4
\n  -v: Verbose output\
Packit a4aae4
\n  -V: Print the version of expr-test\
Packit a4aae4
\n  -p: DDS-file: Read the DDS from DDS-file and create a DDS object,\
Packit a4aae4
\n      then prompt for an expression and parse that expression, given\
Packit a4aae4
\n      the DDS object.\
Packit a4aae4
\n  -e: Evaluate the constraint expression. Must be used with -p.\
Packit a4aae4
\n  -w: Do the whole enchilada. You don't need to supply -p, -e, ...\
Packit a4aae4
\n      This prompts for the constraint expression and the optional\
Packit a4aae4
\n      data file name. NOTE: The CE parser Error objects do not print\
Packit a4aae4
\n      with this option.\
Packit a4aae4
\n  -W: Similar to -w but uses the new (11/2007) intern_data() methods\
Packit a4aae4
\n      in place of the serialize()/deserialize() combination.\
Packit a4aae4
\n  -b: Use periodic/cyclic/changing values. For testing Sequence CEs.\
Packit a4aae4
\n  -f: A file to use for data. Currently only used by -w for sequences.\
Packit a4aae4
\n  -k: A constraint expression to use with the data. Works with -p,\
Packit a4aae4
\n      -e, -t and -w\
Packit a4aae4
\n  -x: Print declarations using the XML syntax. Does not work with the\
Packit a4aae4
\n      data printouts.\
Packit a4aae4
\n  -?: Print usage information";
Packit a4aae4
Packit a4aae4
int main(int argc, char *argv[])
Packit a4aae4
{
Packit a4aae4
    GetOpt getopt(argc, argv, options.c_str());
Packit a4aae4
Packit a4aae4
    int option_char;
Packit a4aae4
    bool scanner_test = false, parser_test = false, evaluate_test = false;
Packit a4aae4
    bool print_constrained = false;
Packit a4aae4
    bool whole_enchalada = false, constraint_expr = false;
Packit a4aae4
    bool whole_intern_enchalada = false;
Packit a4aae4
    bool scan_string = false;
Packit a4aae4
    bool verbose = false;
Packit a4aae4
    bool series_values = false;
Packit a4aae4
    bool xml_syntax = false;
Packit a4aae4
    string dds_file_name;
Packit a4aae4
    string dataset = "";
Packit a4aae4
    string constraint = "";
Packit a4aae4
    TestTypeFactory ttf;
Packit a4aae4
    DDS table(&ttf);
Packit a4aae4
Packit a4aae4
    // Load our one server function...
Packit a4aae4
    ServerFunction *scale = new TestFunction;
Packit a4aae4
    ServerFunctionsList::TheList()->add_function(scale);
Packit a4aae4
Packit a4aae4
    // process options
Packit a4aae4
Packit a4aae4
    while ((option_char = getopt()) != -1)
Packit a4aae4
        switch (option_char) {
Packit a4aae4
        case 'b':
Packit a4aae4
            series_values = true;
Packit a4aae4
            break;
Packit a4aae4
        case 'd':
Packit a4aae4
            ce_exprdebug = true;
Packit a4aae4
            break;
Packit a4aae4
        case 's':
Packit a4aae4
            scanner_test = true;
Packit a4aae4
            break;
Packit a4aae4
        case 'S':
Packit a4aae4
            scanner_test = true;
Packit a4aae4
            scan_string = true;
Packit a4aae4
            constraint = getopt.optarg;
Packit a4aae4
            break;
Packit a4aae4
        case 'p':
Packit a4aae4
            parser_test = true;
Packit a4aae4
            dds_file_name = getopt.optarg;
Packit a4aae4
            break;
Packit a4aae4
        case 'e':
Packit a4aae4
            evaluate_test = true;
Packit a4aae4
            break;
Packit a4aae4
        case 'c':
Packit a4aae4
            print_constrained = true;
Packit a4aae4
            break;
Packit a4aae4
        case 'w':
Packit a4aae4
            whole_enchalada = true;
Packit a4aae4
            dds_file_name = getopt.optarg;
Packit a4aae4
            break;
Packit a4aae4
        case 'W':
Packit a4aae4
            whole_intern_enchalada = true;
Packit a4aae4
            dds_file_name = getopt.optarg;
Packit a4aae4
            break;
Packit a4aae4
        case 'k':
Packit a4aae4
            constraint_expr = true;
Packit a4aae4
            constraint = getopt.optarg;
Packit a4aae4
            break;
Packit a4aae4
        case 'f':
Packit a4aae4
            dataset = getopt.optarg;
Packit a4aae4
            break;
Packit a4aae4
        case 'v':
Packit a4aae4
            verbose = true;
Packit a4aae4
            break;
Packit a4aae4
        case 'V':
Packit a4aae4
            cerr << argv[0] << ": " <<  version << endl;
Packit a4aae4
            exit(0);
Packit a4aae4
        case 'x':
Packit a4aae4
        	xml_syntax = true;
Packit a4aae4
        	break;
Packit a4aae4
        case '?':
Packit a4aae4
        default:
Packit a4aae4
            cerr << usage << endl;
Packit a4aae4
            exit(1);
Packit a4aae4
            break;
Packit a4aae4
        }
Packit a4aae4
Packit a4aae4
    try {
Packit a4aae4
        if (!scanner_test && !parser_test && !evaluate_test
Packit a4aae4
            && !whole_enchalada && !whole_intern_enchalada) {
Packit a4aae4
            cerr << usage << endl;
Packit a4aae4
            exit(1);
Packit a4aae4
        }
Packit a4aae4
        // run selected tests
Packit a4aae4
Packit a4aae4
        if (scanner_test) {
Packit a4aae4
            if (scan_string)
Packit a4aae4
                test_scanner(constraint);
Packit a4aae4
            else
Packit a4aae4
                test_scanner(true);
Packit a4aae4
Packit a4aae4
            exit(0);
Packit a4aae4
        }
Packit a4aae4
Packit a4aae4
        if (parser_test) {
Packit a4aae4
            ConstraintEvaluator eval;
Packit a4aae4
Packit a4aae4
            test_parser(eval, table, dds_file_name, constraint);
Packit a4aae4
        }
Packit a4aae4
Packit a4aae4
        if (evaluate_test) {
Packit a4aae4
            evaluate_dds(table, print_constrained, xml_syntax);
Packit a4aae4
        }
Packit a4aae4
Packit a4aae4
        if (whole_enchalada) {
Packit a4aae4
            constrained_trans(dds_file_name, constraint_expr, constraint, series_values);
Packit a4aae4
        }
Packit a4aae4
        if (whole_intern_enchalada) {
Packit a4aae4
            intern_data_test(dds_file_name, constraint_expr, constraint, series_values);
Packit a4aae4
        }
Packit a4aae4
    }
Packit a4aae4
    catch(Error & e) {
Packit a4aae4
        cerr <
Packit a4aae4
        exit(1);
Packit a4aae4
    }
Packit a4aae4
    catch(exception & e) {
Packit a4aae4
        cerr << "Caught exception: " << e.what() << endl;
Packit a4aae4
        exit(1);
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    exit(0);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
// Instead of reading the tokens from stdin, read them from a string.
Packit a4aae4
Packit a4aae4
void test_scanner(const string & str)
Packit a4aae4
{
Packit a4aae4
    ce_exprrestart(0);
Packit a4aae4
    void *buffer = ce_expr_string(str.c_str());
Packit a4aae4
    ce_expr_switch_to_buffer(buffer);
Packit a4aae4
Packit a4aae4
    test_scanner(false);
Packit a4aae4
Packit a4aae4
    ce_expr_delete_buffer(buffer);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
void test_scanner(bool show_prompt)
Packit a4aae4
{
Packit a4aae4
    if (show_prompt)
Packit a4aae4
        cout << prompt;
Packit a4aae4
Packit a4aae4
    int tok;
Packit a4aae4
    while ((tok = ce_exprlex())) {
Packit a4aae4
        switch (tok) {
Packit a4aae4
        case SCAN_WORD:
Packit a4aae4
            cout << "WORD: " << ce_exprlval.id << endl;
Packit a4aae4
            break;
Packit a4aae4
        case SCAN_STR:
Packit a4aae4
            cout << "STR: " << *ce_exprlval.val.v.s << endl;
Packit a4aae4
            break;
Packit a4aae4
        case SCAN_EQUAL:
Packit a4aae4
            cout << "EQUAL: " << ce_exprlval.op << endl;
Packit a4aae4
            break;
Packit a4aae4
        case SCAN_NOT_EQUAL:
Packit a4aae4
            cout << "NOT_EQUAL: " << ce_exprlval.op << endl;
Packit a4aae4
            break;
Packit a4aae4
        case SCAN_GREATER:
Packit a4aae4
            cout << "GREATER: " << ce_exprlval.op << endl;
Packit a4aae4
            break;
Packit a4aae4
        case SCAN_GREATER_EQL:
Packit a4aae4
            cout << "GREATER_EQL: " << ce_exprlval.op << endl;
Packit a4aae4
            break;
Packit a4aae4
        case SCAN_LESS:
Packit a4aae4
            cout << "LESS: " << ce_exprlval.op << endl;
Packit a4aae4
            break;
Packit a4aae4
        case SCAN_LESS_EQL:
Packit a4aae4
            cout << "LESS_EQL: " << ce_exprlval.op << endl;
Packit a4aae4
            break;
Packit a4aae4
        case SCAN_REGEXP:
Packit a4aae4
            cout << "REGEXP: " << ce_exprlval.op << endl;
Packit a4aae4
            break;
Packit a4aae4
        case SCAN_STAR:
Packit a4aae4
            cout << "STAR: " << ce_exprlval.op << endl;
Packit a4aae4
            break;
Packit a4aae4
        case '.':
Packit a4aae4
            cout << "Field Selector" << endl;
Packit a4aae4
            break;
Packit a4aae4
        case ',':
Packit a4aae4
            cout << "List Element Separator" << endl;
Packit a4aae4
            break;
Packit a4aae4
        case '[':
Packit a4aae4
            cout << "Left Bracket" << endl;
Packit a4aae4
            break;
Packit a4aae4
        case ']':
Packit a4aae4
            cout << "Right Bracket" << endl;
Packit a4aae4
            break;
Packit a4aae4
        case '(':
Packit a4aae4
            cout << "Left Paren" << endl;
Packit a4aae4
            break;
Packit a4aae4
        case ')':
Packit a4aae4
            cout << "Right Paren" << endl;
Packit a4aae4
            break;
Packit a4aae4
        case '{':
Packit a4aae4
            cout << "Left Brace" << endl;
Packit a4aae4
            break;
Packit a4aae4
        case '}':
Packit a4aae4
            cout << "Right Brace" << endl;
Packit a4aae4
            break;
Packit a4aae4
        case ':':
Packit a4aae4
            cout << "Colon" << endl;
Packit a4aae4
            break;
Packit a4aae4
        case '&':
Packit a4aae4
            cout << "Ampersand" << endl;
Packit a4aae4
            break;
Packit a4aae4
        case SCAN_HASH_INT32:
Packit a4aae4
            cout << "Hash Int32" << endl;
Packit a4aae4
            break;
Packit a4aae4
        default:
Packit a4aae4
            cout << "Error: Unrecognized input" << endl;
Packit a4aae4
            break;
Packit a4aae4
        }
Packit a4aae4
Packit a4aae4
        cout << prompt << flush;  // print prompt after output
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
// NB: The DDS is read in via a file because reading from stdin must be
Packit a4aae4
// terminated by EOF. However, the EOF used to terminate the DDS also closes
Packit a4aae4
// stdin and thus the expr scanner exits immediately.
Packit a4aae4
Packit a4aae4
void
Packit a4aae4
test_parser(ConstraintEvaluator & eval, DDS & dds, const string & dds_name,
Packit a4aae4
            string constraint)
Packit a4aae4
{
Packit a4aae4
    try {
Packit a4aae4
        read_table(dds, dds_name, true);
Packit a4aae4
Packit a4aae4
        if (constraint.empty()) {
Packit a4aae4
            cout << "Constraint:";
Packit a4aae4
            char c[256];
Packit a4aae4
            cin.getline(c, 256);
Packit a4aae4
            if (!cin)
Packit a4aae4
                throw InternalErr(__FILE__, __LINE__,
Packit a4aae4
                                  "Could not read the constraint expression\n");
Packit a4aae4
            constraint = c;
Packit a4aae4
        }
Packit a4aae4
Packit a4aae4
        eval.parse_constraint(constraint, dds);
Packit a4aae4
        fprintf(stdout, "Input parsed\n");      // Parser throws on failure.
Packit a4aae4
    }
Packit a4aae4
    catch(Error & e) {
Packit a4aae4
        cerr << e.get_error_message() << endl;
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
// Read a DDS from stdin and build the corresponding DDS. IF PRINT is true,
Packit a4aae4
// print the text representation of that DDS on the stdout. The DDS TABLE is
Packit a4aae4
// modified as a side effect.
Packit a4aae4
//
Packit a4aae4
// Returns: true iff that DDS pasted the semantic_check() mfunc, otherwise
Packit a4aae4
// false.
Packit a4aae4
Packit a4aae4
bool read_table(DDS & table, const string & name, bool print)
Packit a4aae4
{
Packit a4aae4
    table.parse(name);
Packit a4aae4
Packit a4aae4
    if (print)
Packit a4aae4
        table.print(cout);
Packit a4aae4
Packit a4aae4
    if (table.check_semantics(true))
Packit a4aae4
        return true;
Packit a4aae4
    else {
Packit a4aae4
        fprintf(stdout, "Input did not pass semantic checks\n");
Packit a4aae4
        return false;
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
void evaluate_dds(DDS & table, bool print_constrained, bool xml_syntax)
Packit a4aae4
{
Packit a4aae4
    if (print_constrained) {
Packit a4aae4
    	if (xml_syntax)
Packit a4aae4
    		table.print_xml(cout, print_constrained, "");
Packit a4aae4
    	else
Packit a4aae4
    		table.print_constrained(cout);
Packit a4aae4
    }
Packit a4aae4
    else {
Packit a4aae4
        for (DDS::Vars_iter p = table.var_begin(); p != table.var_end(); p++) {
Packit a4aae4
        	if (xml_syntax)
Packit a4aae4
        		(*p)->print_decl(cout, "", print_constrained);
Packit a4aae4
        	else
Packit a4aae4
        		(*p)->print_decl(cout, "", true, true);
Packit a4aae4
        }
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
// Gobble up the MIME header. At one time the MIME Headers were output from
Packit a4aae4
// the server filter programs (not the core software) so we could call
Packit a4aae4
// DDS::send() from this test code and not have to parse the MIME header. But
Packit a4aae4
// in order to get errors to work more reliably the header generation was
Packit a4aae4
// moved `closer to the send'. That is, we put off determining whether to
Packit a4aae4
// send a DDS or an Error object until later. That trade off is that the
Packit a4aae4
// header generation is not buried in the core software. This code simply
Packit a4aae4
// reads until the end of the header is found. 3/25/98 jhrg
Packit a4aae4
Packit a4aae4
void parse_mime(FILE * data_source)
Packit a4aae4
{
Packit a4aae4
    char line[256];
Packit a4aae4
Packit a4aae4
    fgets(line, 256, data_source);
Packit a4aae4
Packit a4aae4
    while (strncmp(line, CRLF, 2) != 0)
Packit a4aae4
        fgets(line, 256, data_source);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
void set_series_values(DDS & dds, bool state)
Packit a4aae4
{
Packit a4aae4
    for (DDS::Vars_iter q = dds.var_begin(); q != dds.var_end(); q++) {
Packit a4aae4
        dynamic_cast < TestCommon & >(**q).set_series_values(state);
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
// Test the transmission of constrained datasets. Use read_table() to read
Packit a4aae4
// the DDS from a file. Once done, prompt for the variable name and
Packit a4aae4
// constraint expression. In a real client-server system the server would
Packit a4aae4
// read the DDS for the entire dataset and send it to the client. The client
Packit a4aae4
// would then respond to the server by asking for a variable given a
Packit a4aae4
// constraint.
Packit a4aae4
//
Packit a4aae4
// Once the constraint has been entered, it is evaluated in the context of
Packit a4aae4
// the DDS using DDS:eval_constraint() (this would happen on the server-side
Packit a4aae4
// in a real system). Once the evaluation is complete,
Packit a4aae4
// DDS::print_constrained() is used to create a DDS describing only those
Packit a4aae4
// parts of the dataset that are to be sent to the client process and written
Packit a4aae4
// to the output stream. After that, the marker `Data:' is written to the
Packit a4aae4
// output stream, followed by the binary data.
Packit a4aae4
Packit a4aae4
void
Packit a4aae4
constrained_trans(const string & dds_name, const bool constraint_expr,
Packit a4aae4
                  const string & constraint, const bool series_values)
Packit a4aae4
{
Packit a4aae4
    // If the CE was not passed in, read it from the command line.
Packit a4aae4
    string ce;
Packit a4aae4
    if (!constraint_expr) {
Packit a4aae4
        cout << "Constraint:";
Packit a4aae4
        char c[256];
Packit a4aae4
        cin.getline(c, 256);
Packit a4aae4
        if (!cin) {
Packit a4aae4
            throw InternalErr(__FILE__, __LINE__, "Could not read the constraint expression\n");
Packit a4aae4
        }
Packit a4aae4
        ce = c;
Packit a4aae4
    }
Packit a4aae4
    else {
Packit a4aae4
        ce = constraint;
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    TestTypeFactory ttf;
Packit a4aae4
    DDS server(&ttf);
Packit a4aae4
    ConstraintEvaluator eval;
Packit a4aae4
Packit a4aae4
    cout << "The complete DDS:" << endl;
Packit a4aae4
    read_table(server, dds_name, true);
Packit a4aae4
Packit a4aae4
    // by default this is false (to get the old-style values that are
Packit a4aae4
    // constant); set series_values to true for testing Sequence constraints.
Packit a4aae4
    // 01/14/05 jhrg And Array constraints, although it's of limited
Packit a4aae4
    // versatility 02/05/07 jhrg
Packit a4aae4
    set_series_values(server, series_values);
Packit a4aae4
Packit a4aae4
    ResponseBuilder df;
Packit a4aae4
    df.set_ce(ce);
Packit a4aae4
    df.set_dataset_name(dds_name);
Packit a4aae4
Packit a4aae4
    ofstream out("expr-test-data.bin", ios::out|ios::trunc|ios::binary);
Packit a4aae4
    df.send_data(out, server, eval, true);
Packit a4aae4
    out.close();
Packit a4aae4
Packit a4aae4
    // Now do what Connect::request_data() does:
Packit a4aae4
    FILE *fp = fopen("expr-test-data.bin", "r");
Packit a4aae4
Packit a4aae4
    Response r(fp, 400);
Packit a4aae4
    Connect c("http://dummy_argument");
Packit a4aae4
Packit a4aae4
    BaseTypeFactory factory;
Packit a4aae4
    DataDDS dds(&factory, "Test_data", "DAP/3.2");      // Must use DataDDS on receiving end
Packit a4aae4
Packit a4aae4
    c.read_data(dds, &r);
Packit a4aae4
Packit a4aae4
    cout << "The data:" << endl;
Packit a4aae4
    for (DDS::Vars_iter q = dds.var_begin(); q != dds.var_end(); q++) {
Packit a4aae4
        (*q)->print_val(cout);
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** This function does what constrained_trans() does but does not use the
Packit a4aae4
    serialize()/deserialize() methods. Instead it uses the new (11/2007)
Packit a4aae4
    intern_data() methods.
Packit a4aae4
Packit a4aae4
    @param dds_name
Packit a4aae4
    @param constraint_expr True is one was given, else false
Packit a4aae4
    @param constraint The constraint expression if \c constraint_expr is
Packit a4aae4
    true.
Packit a4aae4
    @param series_values True if TestTypes should generate 'series values'
Packit a4aae4
    like the DTS. False selects the old-style values. */
Packit a4aae4
void
Packit a4aae4
intern_data_test(const string & dds_name, const bool constraint_expr,
Packit a4aae4
                 const string & constraint, const bool series_values)
Packit a4aae4
{
Packit a4aae4
    // If the CE was not passed in, read it from the command line.
Packit a4aae4
    string ce;
Packit a4aae4
    if (!constraint_expr) {
Packit a4aae4
        cout << "Constraint: ";
Packit a4aae4
        char c[256];
Packit a4aae4
        cin.getline(c, 256);
Packit a4aae4
        if (!cin) {
Packit a4aae4
            throw InternalErr(__FILE__, __LINE__,
Packit a4aae4
                              "Could not read the constraint expression\n");
Packit a4aae4
        }
Packit a4aae4
        ce = c;
Packit a4aae4
    }
Packit a4aae4
    else {
Packit a4aae4
        ce = constraint;
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    TestTypeFactory ttf;
Packit a4aae4
    DDS server(&ttf);
Packit a4aae4
    ConstraintEvaluator eval;
Packit a4aae4
Packit a4aae4
    cout << "The complete DDS:\n";
Packit a4aae4
    read_table(server, dds_name, true);
Packit a4aae4
Packit a4aae4
    // by default this is false (to get the old-style values that are
Packit a4aae4
    // constant); set series_values to true for testing Sequence constraints.
Packit a4aae4
    // 01/14/05 jhrg And Array constraints, although it's of limited
Packit a4aae4
    // versatility 02/05/07 jhrg
Packit a4aae4
    set_series_values(server, series_values);
Packit a4aae4
Packit a4aae4
    eval.parse_constraint(ce, server);  // Throws Error if the ce doesn't parse.
Packit a4aae4
Packit a4aae4
    server.tag_nested_sequences();      // Tag Sequences as Parent or Leaf node.
Packit a4aae4
Packit a4aae4
    if (eval.function_clauses()) {
Packit a4aae4
        DDS *fdds = eval.eval_function_clauses(server);
Packit a4aae4
Packit a4aae4
        for (DDS::Vars_iter i = fdds->var_begin(); i != fdds->var_end(); i++)
Packit a4aae4
            if ((*i)->send_p())
Packit a4aae4
                (*i)->intern_data(eval, *fdds);
Packit a4aae4
Packit a4aae4
        cout << "The data:\n";
Packit a4aae4
Packit a4aae4
        // This code calls 'output_values()' because print_val() does not test
Packit a4aae4
        // the value of send_p(). We need to wrap a method around the calls to
Packit a4aae4
        // print_val() to ensure that only values for variables with send_p() set
Packit a4aae4
        // are called. In the serialize/deserialize case, the 'client' DDS only
Packit a4aae4
        // has variables sent by the 'server' but in the intern_data() case, the
Packit a4aae4
        // whole DDS is still present and only variables selected in the CE have
Packit a4aae4
        // values.
Packit a4aae4
        for (DDS::Vars_iter q = fdds->var_begin(); q != fdds->var_end(); q++) {
Packit a4aae4
            if ((*q)->send_p()) {
Packit a4aae4
                (*q)->print_decl(cout, "", false, false, true);
Packit a4aae4
                cout << " = ";
Packit a4aae4
                dynamic_cast<TestCommon&>(**q).output_values(cout);
Packit a4aae4
                cout << ";\n";
Packit a4aae4
            }
Packit a4aae4
        }
Packit a4aae4
Packit a4aae4
        delete fdds;
Packit a4aae4
    }
Packit a4aae4
    else {
Packit a4aae4
        for (DDS::Vars_iter i = server.var_begin(); i != server.var_end(); i++)
Packit a4aae4
            if ((*i)->send_p())
Packit a4aae4
                (*i)->intern_data(eval, server);
Packit a4aae4
        cout << "The data:\n";
Packit a4aae4
Packit a4aae4
        // This code calls 'output_values()' because print_val() does not test
Packit a4aae4
        // the value of send_p(). We need to wrap a method around the calls to
Packit a4aae4
        // print_val() to ensure that only values for variables with send_p() set
Packit a4aae4
        // are called. In the serialize/deserialize case, the 'client' DDS only
Packit a4aae4
        // has variables sent by the 'server' but in the intern_data() case, the
Packit a4aae4
        // whole DDS is still present and only variables selected in the CE have
Packit a4aae4
        // values.
Packit a4aae4
        for (DDS::Vars_iter q = server.var_begin(); q != server.var_end(); q++) {
Packit a4aae4
            if ((*q)->send_p()) {
Packit a4aae4
                (*q)->print_decl(cout, "", false, false, true);
Packit a4aae4
                cout << " = ";
Packit a4aae4
                dynamic_cast<TestCommon&>(**q).output_values(cout);
Packit a4aae4
                cout << ";\n";
Packit a4aae4
            }
Packit a4aae4
        }
Packit a4aae4
    }
Packit a4aae4
}