|
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 |
}
|