// expressiontests.cpp : Unit tests for Expression classes.
/**
* Copyright (C) 2012 10gen Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
#include "pch.h"
#include "mongo/db/pipeline/expression.h"
#include "mongo/db/pipeline/document.h"
#include "dbtests.h"
namespace ExpressionTests {
/** Check binary equality, ensuring use of the same numeric types. */
static void assertBinaryEqual( const BSONObj& expected, const BSONObj& actual ) {
ASSERT_EQUALS( expected, actual );
ASSERT( expected.binaryEqual( actual ) );
}
/** Convert Value to a wrapped BSONObj with an empty string field name. */
static BSONObj toBson( const intrusive_ptr& value ) {
BSONObjBuilder bob;
value->addToBsonObj( &bob, "" );
return bob.obj();
}
/** Convert Expression to BSON. */
static BSONObj expressionToBson( const intrusive_ptr& expression ) {
BSONObjBuilder bob;
expression->addToBsonObj( &bob, "", true );
return bob.obj().firstElement().embeddedObject().getOwned();
}
/** Create a Document from a BSONObj. */
intrusive_ptr fromBson( BSONObj obj ) {
return Document::createFromBsonObj( &obj );
}
namespace CoerceToBool {
/** Nested expression coerced to true. */
class EvaluateTrue {
public:
void run() {
intrusive_ptr nested =
ExpressionConstant::create( Value::createInt( 5 ) );
intrusive_ptr expression = ExpressionCoerceToBool::create( nested );
ASSERT( expression->evaluate( Document::create() )->getBool() );
}
};
/** Nested expression coerced to false. */
class EvaluateFalse {
public:
void run() {
intrusive_ptr nested =
ExpressionConstant::create( Value::createInt( 0 ) );
intrusive_ptr expression = ExpressionCoerceToBool::create( nested );
ASSERT( !expression->evaluate( Document::create() )->getBool() );
}
};
/** Depdencies forwarded from nested expression. */
class Dependencies {
public:
void run() {
intrusive_ptr nested = ExpressionFieldPath::create( "a.b" );
intrusive_ptr expression = ExpressionCoerceToBool::create( nested );
set dependencies;
expression->addDependencies( dependencies );
ASSERT_EQUALS( 1U, dependencies.size() );
ASSERT_EQUALS( 1U, dependencies.count( "a.b" ) );
}
};
/** Output to BSONObj. */
class AddToBsonObj {
public:
void run() {
intrusive_ptr expression = ExpressionCoerceToBool::create(
ExpressionFieldPath::create("foo"));
// serialized as $and because CoerceToBool isn't an ExpressionNary
assertBinaryEqual(fromjson("{field:{$and:['$foo']}}"), toBsonObj(expression));
}
private:
static BSONObj toBsonObj(const intrusive_ptr& expression) {
BSONObjBuilder bob;
expression->addToBsonObj(&bob, "field", false);
return bob.obj();
}
};
/** Output to BSONArray. */
class AddToBsonArray {
public:
void run() {
intrusive_ptr expression = ExpressionCoerceToBool::create(
ExpressionFieldPath::create("foo"));
// serialized as $and because CoerceToBool isn't an ExpressionNary
assertBinaryEqual(BSON_ARRAY(fromjson("{$and:['$foo']}")), toBsonArray(expression));
}
private:
static BSONArray toBsonArray(const intrusive_ptr& expression) {
BSONArrayBuilder bab;
expression->addToBsonArray(&bab);
return bab.arr();
}
};
// TODO Test optimize(), difficult because a CoerceToBool cannot be output as BSON.
} // namespace CoerceToBool
namespace Compare {
class OptimizeBase {
public:
virtual ~OptimizeBase() {
}
void run() {
BSONObj specObject = BSON( "" << spec() );
BSONElement specElement = specObject.firstElement();
intrusive_ptr expression = Expression::parseOperand( &specElement );
intrusive_ptr optimized = expression->optimize();
ASSERT_EQUALS( expectedFieldRange(),
(bool)dynamic_pointer_cast( optimized ) );
ASSERT_EQUALS( expectedOptimized(), expressionToBson( optimized ) );
}
protected:
virtual BSONObj spec() = 0;
virtual BSONObj expectedOptimized() = 0;
virtual bool expectedFieldRange() = 0;
};
class FieldRangeOptimize : public OptimizeBase {
BSONObj expectedOptimized() { return spec(); }
bool expectedFieldRange() { return true; }
};
class NoOptimize : public OptimizeBase {
BSONObj expectedOptimized() { return spec(); }
bool expectedFieldRange() { return false; }
};
/** Check expected result for expressions depending on constants. */
class ExpectedResultBase : public OptimizeBase {
public:
void run() {
OptimizeBase::run();
BSONObj specObject = BSON( "" << spec() );
BSONElement specElement = specObject.firstElement();
intrusive_ptr expression = Expression::parseOperand( &specElement );
// Check expression spec round trip.
ASSERT_EQUALS( spec(), expressionToBson( expression ) );
// Check evaluation result.
ASSERT_EQUALS( expectedResult(),
toBson( expression->evaluate( Document::create() ) ) );
// Check that the result is the same after optimizing.
intrusive_ptr optimized = expression->optimize();
ASSERT_EQUALS( expectedResult(),
toBson( optimized->evaluate( Document::create() ) ) );
}
protected:
virtual BSONObj spec() = 0;
virtual BSONObj expectedResult() = 0;
private:
virtual BSONObj expectedOptimized() {
return BSON( "$const" << expectedResult().firstElement() );
}
virtual bool expectedFieldRange() { return false; }
};
class ExpectedTrue : public ExpectedResultBase {
BSONObj expectedResult() { return BSON( "" << true ); }
};
class ExpectedFalse : public ExpectedResultBase {
BSONObj expectedResult() { return BSON( "" << false ); }
};
class ParseError {
public:
virtual ~ParseError() {
}
void run() {
BSONObj specObject = BSON( "" << spec() );
BSONElement specElement = specObject.firstElement();
ASSERT_THROWS( Expression::parseOperand( &specElement ), UserException );
}
protected:
virtual BSONObj spec() = 0;
};
/** $eq with first < second. */
class EqLt : public ExpectedFalse {
BSONObj spec() { return BSON( "$eq" << BSON_ARRAY( 1 << 2 ) ); }
};
/** $eq with first == second. */
class EqEq : public ExpectedTrue {
BSONObj spec() { return BSON( "$eq" << BSON_ARRAY( 1 << 1 ) ); }
};
/** $eq with first > second. */
class EqGt : public ExpectedFalse {
BSONObj spec() { return BSON( "$eq" << BSON_ARRAY( 1 << 0 ) ); }
};
/** $ne with first < second. */
class NeLt : public ExpectedTrue {
BSONObj spec() { return BSON( "$ne" << BSON_ARRAY( 1 << 2 ) ); }
};
/** $ne with first == second. */
class NeEq : public ExpectedFalse {
BSONObj spec() { return BSON( "$ne" << BSON_ARRAY( 1 << 1 ) ); }
};
/** $ne with first > second. */
class NeGt : public ExpectedTrue {
BSONObj spec() { return BSON( "$ne" << BSON_ARRAY( 1 << 0 ) ); }
};
/** $gt with first < second. */
class GtLt : public ExpectedFalse {
BSONObj spec() { return BSON( "$gt" << BSON_ARRAY( 1 << 2 ) ); }
};
/** $gt with first == second. */
class GtEq : public ExpectedFalse {
BSONObj spec() { return BSON( "$gt" << BSON_ARRAY( 1 << 1 ) ); }
};
/** $gt with first > second. */
class GtGt : public ExpectedTrue {
BSONObj spec() { return BSON( "$gt" << BSON_ARRAY( 1 << 0 ) ); }
};
/** $gte with first < second. */
class GteLt : public ExpectedFalse {
BSONObj spec() { return BSON( "$gte" << BSON_ARRAY( 1 << 2 ) ); }
};
/** $gte with first == second. */
class GteEq : public ExpectedTrue {
BSONObj spec() { return BSON( "$gte" << BSON_ARRAY( 1 << 1 ) ); }
};
/** $gte with first > second. */
class GteGt : public ExpectedTrue {
BSONObj spec() { return BSON( "$gte" << BSON_ARRAY( 1 << 0 ) ); }
};
/** $lt with first < second. */
class LtLt : public ExpectedTrue {
BSONObj spec() { return BSON( "$lt" << BSON_ARRAY( 1 << 2 ) ); }
};
/** $lt with first == second. */
class LtEq : public ExpectedFalse {
BSONObj spec() { return BSON( "$lt" << BSON_ARRAY( 1 << 1 ) ); }
};
/** $lt with first > second. */
class LtGt : public ExpectedFalse {
BSONObj spec() { return BSON( "$lt" << BSON_ARRAY( 1 << 0 ) ); }
};
/** $lte with first < second. */
class LteLt : public ExpectedTrue {
BSONObj spec() { return BSON( "$lte" << BSON_ARRAY( 1 << 2 ) ); }
};
/** $lte with first == second. */
class LteEq : public ExpectedTrue {
BSONObj spec() { return BSON( "$lte" << BSON_ARRAY( 1 << 1 ) ); }
};
/** $lte with first > second. */
class LteGt : public ExpectedFalse {
BSONObj spec() { return BSON( "$lte" << BSON_ARRAY( 1 << 0 ) ); }
};
/** $cmp with first < second. */
class CmpLt : public ExpectedResultBase {
BSONObj spec() { return BSON( "$cmp" << BSON_ARRAY( 1 << 2 ) ); }
BSONObj expectedResult() { return BSON( "" << -1 ); }
};
/** $cmp with first == second. */
class CmpEq : public ExpectedResultBase {
BSONObj spec() { return BSON( "$cmp" << BSON_ARRAY( 1 << 1 ) ); }
BSONObj expectedResult() { return BSON( "" << 0 ); }
};
/** $cmp with first > second. */
class CmpGt : public ExpectedResultBase {
BSONObj spec() { return BSON( "$cmp" << BSON_ARRAY( 1 << 0 ) ); }
BSONObj expectedResult() { return BSON( "" << 1 ); }
};
/** $cmp results are bracketed to an absolute value of 1. */
class CmpBracketed : public ExpectedResultBase {
BSONObj spec() { return BSON( "$cmp" << BSON_ARRAY( "z" << "a" ) ); }
BSONObj expectedResult() { return BSON( "" << 1 ); }
};
/** Zero operands provided. */
class ZeroOperands : public ParseError {
BSONObj spec() { return BSON( "$ne" << BSONArray() ); }
};
/** One operand provided. */
class OneOperand : public ParseError {
BSONObj spec() { return BSON( "$eq" << BSON_ARRAY( 1 ) ); }
};
/** Three operands provided. */
class ThreeOperands : public ParseError {
BSONObj spec() { return BSON( "$gt" << BSON_ARRAY( 2 << 3 << 4 ) ); }
};
/** Incompatible types cannot be compared. */
class IncompatibleTypes {
public:
void run() {
BSONObj specObject = BSON( "" << BSON( "$ne" << BSON_ARRAY( "a" << 1 ) ) );
BSONElement specElement = specObject.firstElement();
intrusive_ptr expression = Expression::parseOperand( &specElement );
ASSERT_THROWS( expression->evaluate( Document::create() ), UserException );
}
};
/**
* An expression depending on constants is optimized to a constant via
* ExpressionNary::optimize().
*/
class OptimizeConstants : public OptimizeBase {
BSONObj spec() { return BSON( "$eq" << BSON_ARRAY( 1 << 1 ) ); }
BSONObj expectedOptimized() { return BSON( "$const" << true ); }
bool expectedFieldRange() { return false; }
};
/** $cmp is not optimized. */
class NoOptimizeCmp : public NoOptimize {
BSONObj spec() { return BSON( "$cmp" << BSON_ARRAY( 1 << "$a" ) ); }
};
/** $ne is not optimized. */
class NoOptimizeNe : public NoOptimize {
BSONObj spec() { return BSON( "$ne" << BSON_ARRAY( 1 << "$a" ) ); }
};
/** No optimization is performend without a constant. */
class NoOptimizeNoConstant : public NoOptimize {
BSONObj spec() { return BSON( "$ne" << BSON_ARRAY( "$a" << "$b" ) ); }
};
/** No optimization is performend without an immediate field path. */
class NoOptimizeWithoutFieldPath : public NoOptimize {
BSONObj spec() {
return BSON( "$eq" << BSON_ARRAY( BSON( "$and" << BSON_ARRAY( "$a" ) ) << 1 ) );
}
};
/** No optimization is performend without an immediate field path. */
class NoOptimizeWithoutFieldPathReverse : public NoOptimize {
BSONObj spec() {
return BSON( "$eq" << BSON_ARRAY( 1 << BSON( "$and" << BSON_ARRAY( "$a" ) ) ) );
}
};
/** An equality expression is optimized. */
class OptimizeEq : public FieldRangeOptimize {
BSONObj spec() { return BSON( "$eq" << BSON_ARRAY( "$a" << 1 ) ); }
};
/** A reverse sense equality expression is optimized. */
class OptimizeEqReverse : public FieldRangeOptimize {
BSONObj spec() { return BSON( "$eq" << BSON_ARRAY( 1 << "$a" ) ); }
BSONObj expectedOptimized() { return BSON( "$eq" << BSON_ARRAY( "$a" << 1 ) ); }
};
/** A $lt expression is optimized. */
class OptimizeLt : public FieldRangeOptimize {
BSONObj spec() { return BSON( "$lt" << BSON_ARRAY( "$a" << 1 ) ); }
};
/** A reverse sense $lt expression is optimized. */
class OptimizeLtReverse : public FieldRangeOptimize {
BSONObj spec() { return BSON( "$lt" << BSON_ARRAY( 1 << "$a" ) ); }
BSONObj expectedOptimized() { return BSON( "$gt" << BSON_ARRAY( "$a" << 1 ) ); }
};
/** A $lte expression is optimized. */
class OptimizeLte : public FieldRangeOptimize {
BSONObj spec() { return BSON( "$lte" << BSON_ARRAY( "$b" << 2 ) ); }
};
/** A reverse sense $lte expression is optimized. */
class OptimizeLteReverse : public FieldRangeOptimize {
BSONObj spec() { return BSON( "$lte" << BSON_ARRAY( 2 << "$b" ) ); }
BSONObj expectedOptimized() { return BSON( "$gte" << BSON_ARRAY( "$b" << 2 ) ); }
};
/** A $gt expression is optimized. */
class OptimizeGt : public FieldRangeOptimize {
BSONObj spec() { return BSON( "$gt" << BSON_ARRAY( "$b" << 2 ) ); }
};
/** A reverse sense $gt expression is optimized. */
class OptimizeGtReverse : public FieldRangeOptimize {
BSONObj spec() { return BSON( "$gt" << BSON_ARRAY( 2 << "$b" ) ); }
BSONObj expectedOptimized() { return BSON( "$lt" << BSON_ARRAY( "$b" << 2 ) ); }
};
/** A $gte expression is optimized. */
class OptimizeGte : public FieldRangeOptimize {
BSONObj spec() { return BSON( "$gte" << BSON_ARRAY( "$b" << 2 ) ); }
};
/** A reverse sense $gte expression is optimized. */
class OptimizeGteReverse : public FieldRangeOptimize {
BSONObj spec() { return BSON( "$gte" << BSON_ARRAY( 2 << "$b" ) ); }
BSONObj expectedOptimized() { return BSON( "$lte" << BSON_ARRAY( "$b" << 2 ) ); }
};
} // namespace Compare
namespace Constant {
/** Create an ExpressionConstant from a Value. */
class Create {
public:
void run() {
intrusive_ptr expression =
ExpressionConstant::create( Value::createInt( 5 ) );
assertBinaryEqual( BSON( "" << 5 ),
toBson( expression->evaluate( Document::create() ) ) );
}
};
/** Create an ExpressionConstant from a BsonElement. */
class CreateFromBsonElement {
public:
void run() {
BSONObj spec = BSON( "IGNORED_FIELD_NAME" << "foo" );
BSONElement specElement = spec.firstElement();
intrusive_ptr expression =
ExpressionConstant::createFromBsonElement( &specElement );
assertBinaryEqual( BSON( "" << "foo" ),
toBson( expression->evaluate( Document::create() ) ) );
}
};
/** No optimization is performed. */
class Optimize {
public:
void run() {
intrusive_ptr expression =
ExpressionConstant::create( Value::createInt( 5 ) );
// An attempt to optimize returns the Expression itself.
ASSERT_EQUALS( expression, expression->optimize() );
}
};
/** No dependencies. */
class Dependencies {
public:
void run() {
intrusive_ptr expression =
ExpressionConstant::create( Value::createInt( 5 ) );
set dependencies;
expression->addDependencies( dependencies );
ASSERT_EQUALS( 0U, dependencies.size() );
}
};
/** Output to BSONObj. */
class AddToBsonObj {
public:
void run() {
intrusive_ptr expression =
ExpressionConstant::create( Value::createInt( 5 ) );
// The constant is copied out as is.
assertBinaryEqual( BSON( "field" << 5 ), toBsonObj( expression, false ) );
// The constant is replaced with a $ expression.
assertBinaryEqual( BSON( "field" << BSON( "$const" << 5 ) ),
toBsonObj( expression, true ) );
}
private:
static BSONObj toBsonObj( const intrusive_ptr& expression,
bool requireExpression ) {
BSONObjBuilder bob;
expression->addToBsonObj( &bob, "field", requireExpression );
return bob.obj();
}
};
/** Output to BSONArray. */
class AddToBsonArray {
public:
void run() {
intrusive_ptr expression =
ExpressionConstant::create( Value::createInt( 5 ) );
// The constant is copied out as is.
assertBinaryEqual( BSON_ARRAY( 5 ), toBsonArray( expression ) );
}
private:
static BSONObj toBsonArray( const intrusive_ptr& expression ) {
BSONArrayBuilder bab;
expression->addToBsonArray( &bab );
return bab.obj();
}
};
} // namespace Constant
namespace FieldPath {
/** The provided field path does not pass validation. */
class Invalid {
public:
void run() {
ASSERT_THROWS( ExpressionFieldPath::create( "" ), UserException );
}
};
/** No optimization is performed. */
class Optimize {
public:
void run() {
intrusive_ptr expression = ExpressionFieldPath::create( "a" );
// An attempt to optimize returns the Expression itself.
ASSERT_EQUALS( expression, expression->optimize() );
}
};
/** The field path itself is a dependency. */
class Dependencies {
public:
void run() {
intrusive_ptr expression = ExpressionFieldPath::create( "a.b" );
set dependencies;
expression->addDependencies( dependencies );
ASSERT_EQUALS( 1U, dependencies.size() );
ASSERT_EQUALS( 1U, dependencies.count( "a.b" ) );
}
};
/** Field path target field is missing. */
class Missing {
public:
void run() {
intrusive_ptr expression = ExpressionFieldPath::create( "a" );
// Result is undefined.
assertBinaryEqual( fromjson( "{'':undefined}" ),
toBson( expression->evaluate( Document::create() ) ) );
}
};
/** Simple case where the target field is present. */
class Present {
public:
void run() {
intrusive_ptr expression = ExpressionFieldPath::create( "a" );
assertBinaryEqual( fromjson( "{'':123}" ),
toBson( expression->evaluate
( fromBson( BSON( "a" << 123 ) ) ) ) );
}
};
/** Target field parent is null. */
class NestedBelowNull {
public:
void run() {
intrusive_ptr expression = ExpressionFieldPath::create( "a.b" );
assertBinaryEqual( fromjson( "{'':undefined}" ),
toBson( expression->evaluate
( fromBson( fromjson( "{a:null}" ) ) ) ) );
}
};
/** Target field parent is undefined. */
class NestedBelowUndefined {
public:
void run() {
intrusive_ptr expression = ExpressionFieldPath::create( "a.b" );
assertBinaryEqual( fromjson( "{'':undefined}" ),
toBson( expression->evaluate
( fromBson( fromjson( "{a:undefined}" ) ) ) ) );
}
};
/** Target field parent is an integer. */
class NestedBelowInt {
public:
void run() {
intrusive_ptr expression = ExpressionFieldPath::create( "a.b" );
assertBinaryEqual( fromjson( "{'':undefined}" ),
toBson( expression->evaluate
( fromBson( BSON( "a" << 2 ) ) ) ) );
}
};
/** A value in a nested object. */
class NestedValue {
public:
void run() {
intrusive_ptr expression = ExpressionFieldPath::create( "a.b" );
assertBinaryEqual( BSON( "" << 55 ),
toBson( expression->evaluate
( fromBson( BSON( "a" << BSON( "b" << 55 ) ) ) ) ) );
}
};
/** Target field within an empty object. */
class NestedBelowEmptyObject {
public:
void run() {
intrusive_ptr expression = ExpressionFieldPath::create( "a.b" );
assertBinaryEqual( fromjson( "{'':undefined}" ),
toBson( expression->evaluate
( fromBson( BSON( "a" << BSONObj() ) ) ) ) );
}
};
/** Target field within an empty array. */
class NestedBelowEmptyArray {
public:
void run() {
intrusive_ptr expression = ExpressionFieldPath::create( "a.b" );
assertBinaryEqual( BSON( "" << BSONArray() ),
toBson( expression->evaluate
( fromBson( BSON( "a" << BSONArray() ) ) ) ) );
}
};
/** Target field within an array containing null. */
class NestedBelowArrayWithNull {
public:
void run() {
intrusive_ptr expression = ExpressionFieldPath::create( "a.b" );
assertBinaryEqual( fromjson( "{'':[null]}" ),
toBson( expression->evaluate
( fromBson( fromjson( "{a:[null]}" ) ) ) ) );
}
};
/** Target field within an array containing undefined. */
class NestedBelowArrayWithUndefined {
public:
void run() {
intrusive_ptr expression = ExpressionFieldPath::create( "a.b" );
assertBinaryEqual( fromjson( "{'':[undefined]}" ),
toBson( expression->evaluate
( fromBson( fromjson( "{a:[undefined]}" ) ) ) ) );
}
};
/** Target field within an array containing an integer. */
class NestedBelowArrayWithInt {
public:
void run() {
intrusive_ptr expression = ExpressionFieldPath::create( "a.b" );
ASSERT_THROWS( expression->evaluate( fromBson( fromjson( "{a:[1]}" ) ) ),
UserException );
}
};
/** Target field within an array. */
class NestedWithinArray {
public:
void run() {
intrusive_ptr expression = ExpressionFieldPath::create( "a.b" );
assertBinaryEqual( fromjson( "{'':[9]}" ),
toBson( expression->evaluate
( fromBson( fromjson( "{a:[{b:9}]}" ) ) ) ) );
}
};
/** Multiple value types within an array. */
class MultipleArrayValues {
public:
void run() {
intrusive_ptr expression = ExpressionFieldPath::create( "a.b" );
assertBinaryEqual( fromjson( "{'':[9,null,undefined,undefined,20,undefined]}" ),
toBson( expression->evaluate
( fromBson( fromjson
( "{a:[{b:9},null,undefined,{g:4},{b:20},{}]}"
) ) ) ) );
}
};
/** Expanding values within nested arrays. */
class ExpandNestedArrays {
public:
void run() {
intrusive_ptr expression = ExpressionFieldPath::create( "a.b.c" );
assertBinaryEqual( fromjson( "{'':[[1,2],3,[4],[[5]],[6,7]]}" ),
toBson
( expression->evaluate
( fromBson
( fromjson( "{a:[{b:[{c:1},{c:2}]},"
"{b:{c:3}},"
"{b:[{c:4}]},"
"{b:[{c:[5]}]},"
"{b:{c:[6,7]}}]}" ) ) ) ) );
}
};
/** Add to a BSONObj. */
class AddToBsonObj {
public:
void run() {
intrusive_ptr expression = ExpressionFieldPath::create( "a.b.c" );
BSONObjBuilder bob;
expression->addToBsonObj( &bob, "foo", false );
assertBinaryEqual( BSON( "foo" << "$a.b.c" ), bob.obj() );
}
};
/** Add to a BSONArray. */
class AddToBsonArray {
public:
void run() {
intrusive_ptr expression = ExpressionFieldPath::create( "a.b.c" );
BSONArrayBuilder bab;
expression->addToBsonArray( &bab );
assertBinaryEqual( BSON_ARRAY( "$a.b.c" ), bab.arr() );
}
};
} // namespace FieldPath
class All : public Suite {
public:
All() : Suite( "expression" ) {
}
void setupTests() {
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
add();
}
} myall;
} // namespace ExpressionTests