"Fossies" - the Fresh Open Source Software Archive

Member "aqsis-1.8.2/libs/riutil/ribparser_test.cpp" (24 Aug 2012, 43271 Bytes) of package /linux/privat/aqsis-1.8.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 // Aqsis
    2 // Copyright (C) 2001, Paul C. Gregory and the other authors and contributors
    3 // All rights reserved.
    4 //
    5 // Redistribution and use in source and binary forms, with or without
    6 // modification, are permitted provided that the following conditions are met:
    7 //
    8 // * Redistributions of source code must retain the above copyright notice,
    9 //   this list of conditions and the following disclaimer.
   10 // * Redistributions in binary form must reproduce the above copyright notice,
   11 //   this list of conditions and the following disclaimer in the documentation
   12 //   and/or other materials provided with the distribution.
   13 // * Neither the name of the software's owners nor the names of its
   14 //   contributors may be used to endorse or promote products derived from this
   15 //   software without specific prior written permission.
   16 //
   17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   27 // POSSIBILITY OF SUCH DAMAGE.
   28 //
   29 // (This is the New BSD license)
   30 
   31 /// \file
   32 ///
   33 /// \brief RIB parser tests
   34 /// \author Chris Foster [chris42f (at) g mail (d0t) com]
   35 ///
   36 
   37 #include <aqsis/aqsis.h>
   38 
   39 #define BOOST_TEST_DYN_LINK
   40 
   41 #include "ribparser_impl.h"
   42 
   43 #include <cfloat>
   44 #include <cstdlib>
   45 #include <sstream>
   46 
   47 #include <boost/assign/std/vector.hpp>
   48 #include <boost/test/auto_unit_test.hpp>
   49 
   50 #include <aqsis/math/math.h>
   51 #include <aqsis/riutil/tokendictionary.h>
   52 #include <aqsis/riutil/errorhandler.h>
   53 
   54 using namespace boost::assign; // necessary for container initialisation operators.
   55 
   56 using namespace Aqsis;
   57 
   58 //------------------------------------------------------------------------------
   59 // Test setup.  Unfortunately we need a LOT of this :(
   60 //------------------------------------------------------------------------------
   61 namespace {
   62 // struct wrapping a request name for use in parser parameter vector.
   63 struct Req
   64 {
   65     std::string name;
   66 
   67     Req() : name() {}
   68     explicit Req(const char* name) : name(name) {}
   69     Req(const Req& rq) : name(rq.name) {}
   70 
   71     bool operator==(const Req& rhs) const
   72     {
   73         return name == rhs.name;
   74     }
   75 };
   76 
   77 namespace printer_funcs
   78 {
   79     template<typename T>
   80     void ribTokenPrint(std::ostream& out, const T& v) { out << v; }
   81 
   82     // Wrap strings in token lists with a pair of " chars
   83     void ribTokenPrint(std::ostream& out, const std::string& s)
   84     {
   85         out << '"' << s << '"';
   86     }
   87 
   88     // Printer functions for use with boost.test test tools
   89     // We put these operator<<() in a namespace so that they can be introduced
   90     // into namespace boost in a controllable way.
   91 
   92     // Insert a std::vector into a stream in RIB format.
   93     template<typename T>
   94     std::ostream& operator<<(std::ostream& out, const std::vector<T>& v)
   95     {
   96         out << "[";
   97         for(int i = 0, end = v.size(); i < end; ++i)
   98         {
   99             ribTokenPrint(out, v[i]);
  100             if(i != end-1)
  101                 out << " ";
  102         }
  103         out << "]";
  104         return out;
  105     }
  106 
  107     // Print a Ri::Array
  108     template<typename T>
  109     std::ostream& operator<<(std::ostream& out, const Ri::Array<T>& v)
  110     {
  111         out << "[";
  112         for(int i = 0, end = v.size(); i < end; ++i)
  113         {
  114             ribTokenPrint(out, v[i]);
  115             if(i != end-1)
  116                 out << " ";
  117         }
  118         out << "]";
  119         return out;
  120     }
  121 
  122     std::ostream& operator<<(std::ostream& out, const Ri::Param& p)
  123     {
  124         out << CqPrimvarToken(p.spec(), p.name());
  125         return out;
  126     }
  127 
  128     std::ostream& operator<<(std::ostream& out, const Ri::TypeSpec& spec)
  129     {
  130         CqPrimvarToken tok(spec, "");
  131         out << tok.Class() << " " << tok.type();
  132         if(tok.count() != 1)
  133             out << "[" << tok.count() << "]";
  134         return out;
  135     }
  136 
  137     // Insert a Req into a stream.
  138     std::ostream& operator<<(std::ostream& out, const Req& r)
  139     {
  140         out << r.name;
  141         return out;
  142     }
  143 }
  144 
  145 // Introduce the printer funcs into the necessary namespaces so that lookup can
  146 // find them (ugh, is there a better way to do this?)  One alternative would be
  147 // to just disable printing using something like
  148 //
  149 //   BOOST_TEST_DONT_PRINT_LOG_VALUE(Ri::Param);
  150 //
  151 } // anon. namespace 
  152 
  153 namespace Aqsis { namespace Ri {
  154     using printer_funcs::operator<<;
  155 }}
  156 
  157 // Note that BOOST_AUTO_TEST_SUITE uses a namespace as implementation, so we
  158 // need to take care when mixing it with our own namespaces.
  159 BOOST_AUTO_TEST_SUITE(rib_parser_tests)
  160 
  161 namespace {
  162 using printer_funcs::operator<<;
  163 
  164 //------------------------------------------------------------------------------
  165 // Types for MockRibToken
  166 enum MockTokType
  167 {
  168     Type_Int,
  169     Type_Float,
  170     Type_String,
  171     Type_IntArray,
  172     Type_FloatArray,
  173     Type_StringArray,
  174     Type_Request,
  175     Type_Ignore
  176 };
  177 
  178 // Tag struct to indicate an empty MockRibToken, used to reconcile differing
  179 // RIB and RI forms of requests where necessary.
  180 struct IgnoreType {};
  181 static IgnoreType IgnoreParam;
  182 
  183 
  184 // Cheap and nasty variant holding RIB tokens
  185 //
  186 // Yeah, boost::variant would allow me to avoid implementing this class, but
  187 // the error messages are absolutely insane, to the point of making the code
  188 // unmaintainable.
  189 //
  190 struct MockRibToken
  191 {
  192 private:
  193     MockTokType m_type;
  194 
  195     int m_int;
  196     float m_float;
  197     std::string m_string;
  198     Req m_request;
  199     std::vector<int> m_ints;
  200     std::vector<float> m_floats;
  201     std::vector<std::string> m_strings;
  202 
  203 public:
  204     explicit MockRibToken(int i)                    : m_type(Type_Int), m_int(i) { }
  205     explicit MockRibToken(float f)                  : m_type(Type_Float), m_float(f) { }
  206     explicit MockRibToken(const char* s)            : m_type(Type_String), m_string(s) { }
  207     explicit MockRibToken(const std::string& s)     : m_type(Type_String), m_string(s) { }
  208     explicit MockRibToken(const Req& request)       : m_type(Type_Request), m_request(request) { }
  209     explicit MockRibToken(const std::vector<int>& v)         : m_type(Type_IntArray), m_ints(v) { }
  210     explicit MockRibToken(const std::vector<float>& v)       : m_type(Type_FloatArray), m_floats(v) { }
  211     explicit MockRibToken(const std::vector<std::string>& v) : m_type(Type_StringArray), m_strings(v) { }
  212     explicit MockRibToken(const Ri::IntArray& v)    : m_type(Type_IntArray), m_ints(v.begin(), v.end()) { }
  213     explicit MockRibToken(const Ri::FloatArray& v)  : m_type(Type_FloatArray), m_floats(v.begin(), v.end()) { }
  214     explicit MockRibToken(const Ri::StringArray& v) : m_type(Type_StringArray), m_strings(v.begin(), v.end()) { }
  215     explicit MockRibToken(const IgnoreType&)        : m_type(Type_Ignore) { }
  216 
  217     MockTokType type() const { return m_type; }
  218 
  219     int getInt() const                   { BOOST_REQUIRE(m_type == Type_Int); return m_int; }
  220     float getFloat() const               { BOOST_REQUIRE(m_type == Type_Float); return m_float; }
  221     const std::string& getString() const { BOOST_REQUIRE(m_type == Type_String); return m_string; }
  222     const Req& getReq() const            { BOOST_REQUIRE(m_type == Type_Request); return m_request; }
  223     const std::vector<int>& getIntArray() const            { BOOST_REQUIRE(m_type == Type_IntArray); return m_ints; }
  224     const std::vector<float>& getFloatArray() const        { BOOST_REQUIRE(m_type == Type_FloatArray); return m_floats; }
  225     const std::vector<std::string>& getStringArray() const { BOOST_REQUIRE(m_type == Type_StringArray); return m_strings; }
  226 
  227     bool operator==(const MockRibToken& rhs) const
  228     {
  229         if(m_type == Type_Ignore)
  230         {
  231             // Always consider an ignored param to be "equal" to whatever
  232             // we feed in.  This is for convenience when comparing RIB and
  233             // RI forms of a request.
  234             return true;
  235         }
  236         if(m_type != rhs.m_type)
  237             return false;
  238         switch(m_type)
  239         {
  240             case Type_Int:         return getInt() == rhs.getInt();
  241             case Type_Float:       return getFloat() == rhs.getFloat();
  242             case Type_String:      return getString() == rhs.getString();
  243             case Type_IntArray:    return getIntArray() == rhs.getIntArray();
  244             case Type_FloatArray:  return getFloatArray() == rhs.getFloatArray();
  245             case Type_StringArray: return getStringArray() == rhs.getStringArray();
  246             case Type_Request:     return getReq() == rhs.getReq();
  247             case Type_Ignore:      return true;
  248         }
  249         BOOST_REQUIRE(0 && "unrecognised m_type??");
  250         return false;
  251     }
  252 };
  253 
  254 typedef std::vector<MockRibToken> TokenVec;
  255 
  256 std::ostream& operator<<(std::ostream& out, const MockRibToken& tok)
  257 {
  258 //    if(&out != &std::cerr)
  259 //        std::cerr << "_X" << tok.type() << tok << "X_";
  260     switch(tok.type())
  261     {
  262         case Type_Int:          out << tok.getInt();        break;
  263         case Type_Float:        out << tok.getFloat();      break;
  264         case Type_String:       out << '"' << tok.getString() << '"'; break;
  265         case Type_IntArray:     out << tok.getIntArray();   break;
  266         case Type_FloatArray:   out << tok.getFloatArray(); break;
  267         case Type_StringArray:  out << tok.getStringArray();break;
  268         case Type_Request:      out << tok.getReq().name;   break;
  269         case Type_Ignore:                                   break;
  270     }
  271     return out;
  272 }
  273 
  274 // Compare the contents of a std::vector to an Ri::Array
  275 template<typename T1, typename T2>
  276 bool operator==(const std::vector<T1>& v1, const Ri::Array<T2>& v2)
  277 {
  278     if(v1.size() != v2.size())
  279         return false;
  280     for(int i = 0, end = v1.size(); i < end; ++i)
  281     {
  282         if(v1[i] != v2[i])
  283             return false;
  284     }
  285     return true;
  286 }
  287 
  288 // Compare a token containing an array to an Ri::Param array
  289 //
  290 // assert if the token doesn't contain an array.
  291 bool operator==(const MockRibToken& lhs, const Ri::Param& rhs)
  292 {
  293     switch(lhs.type())
  294     {
  295         case Type_IntArray:    return lhs.getIntArray() == rhs.intData();
  296         case Type_FloatArray:  return lhs.getFloatArray() == rhs.floatData();
  297         case Type_StringArray: return lhs.getStringArray() == rhs.stringData();
  298         default:
  299             BOOST_CHECK_EQUAL(lhs.type(), MockTokType(100)); // hack to print type.
  300             BOOST_REQUIRE(0 && "MockRibToken Ri::Param compare not implemented for type");
  301     }
  302     return false;
  303 }
  304 
  305 
  306 // Exception to throw from MockRenderer::Error
  307 struct MockRendererError
  308 {
  309     std::string message;
  310     MockRendererError(const std::string& msg) : message(msg) {}
  311 };
  312 
  313 // Some dummy symbols returned by MockRenderer.
  314 RtConstBasis g_mockBasis = {{1,0,0,0}, {0,2,0,0}, {0,0,3,0}, {0,0,0,4}};
  315 
  316 RtVoid mockProcSubdivFunc( RtPointer data, RtFloat detail )
  317 {}
  318 RtFloat mockFilterFunc(RtFloat x, RtFloat y, RtFloat xwidth, RtFloat ywidth)
  319 {
  320     return 1;
  321 }
  322 
  323 // Mock implementation of Ri::Renderer.
  324 class MockRenderer : public Ri::Renderer
  325 {
  326     public:
  327         MockRenderer() {}
  328 
  329         // Define all methods, except those which are tested.
  330         /*[[[cog
  331         from codegenutils import *
  332 
  333         riXml = parseXml(riXmlPath)
  334 
  335         # Here's all methods which are currently tested:
  336         testedMethods = set([
  337             'Declare',
  338             'DepthOfField',
  339             'PixelFilter',
  340             'ColorSamples',
  341             'Option',
  342             'Color',
  343             'LightSource',
  344             'Illuminate',
  345             'Transform',
  346             'Basis',
  347             'SubdivisionMesh',
  348             'Sphere',
  349             'Hyperboloid',
  350             'Points',
  351             'Procedural',
  352             'ObjectBegin',
  353             'MotionBegin',
  354             'MakeOcclusion',
  355         ])
  356 
  357         for p in riXml.findall('Procedures/Procedure'):
  358             if p.findall('Rib'):
  359                 decl = riCxxMethodDecl(p)
  360                 procName = p.findtext('Name')
  361                 if procName in testedMethods:
  362                     cog.outl('// %s is tested' % (procName,))
  363                     decl = 'virtual %s;' % (decl,)
  364                 else:
  365                     decl = 'virtual %s {}' % (decl,)
  366                 cog.outl(wrapDecl(decl, 72, wrapIndent=20))
  367         ]]]*/
  368         // Declare is tested
  369         virtual RtVoid Declare(RtConstString name, RtConstString declaration);
  370         virtual RtVoid FrameBegin(RtInt number) {}
  371         virtual RtVoid FrameEnd() {}
  372         virtual RtVoid WorldBegin() {}
  373         virtual RtVoid WorldEnd() {}
  374         virtual RtVoid IfBegin(RtConstString condition) {}
  375         virtual RtVoid ElseIf(RtConstString condition) {}
  376         virtual RtVoid Else() {}
  377         virtual RtVoid IfEnd() {}
  378         virtual RtVoid Format(RtInt xresolution, RtInt yresolution,
  379                             RtFloat pixelaspectratio) {}
  380         virtual RtVoid FrameAspectRatio(RtFloat frameratio) {}
  381         virtual RtVoid ScreenWindow(RtFloat left, RtFloat right, RtFloat bottom,
  382                             RtFloat top) {}
  383         virtual RtVoid CropWindow(RtFloat xmin, RtFloat xmax, RtFloat ymin,
  384                             RtFloat ymax) {}
  385         virtual RtVoid Projection(RtConstToken name, const ParamList& pList) {}
  386         virtual RtVoid Clipping(RtFloat cnear, RtFloat cfar) {}
  387         virtual RtVoid ClippingPlane(RtFloat x, RtFloat y, RtFloat z,
  388                             RtFloat nx, RtFloat ny, RtFloat nz) {}
  389         // DepthOfField is tested
  390         virtual RtVoid DepthOfField(RtFloat fstop, RtFloat focallength,
  391                             RtFloat focaldistance);
  392         virtual RtVoid Shutter(RtFloat opentime, RtFloat closetime) {}
  393         virtual RtVoid PixelVariance(RtFloat variance) {}
  394         virtual RtVoid PixelSamples(RtFloat xsamples, RtFloat ysamples) {}
  395         // PixelFilter is tested
  396         virtual RtVoid PixelFilter(RtFilterFunc function, RtFloat xwidth,
  397                             RtFloat ywidth);
  398         virtual RtVoid Exposure(RtFloat gain, RtFloat gamma) {}
  399         virtual RtVoid Imager(RtConstToken name, const ParamList& pList) {}
  400         virtual RtVoid Quantize(RtConstToken type, RtInt one, RtInt min,
  401                             RtInt max, RtFloat ditheramplitude) {}
  402         virtual RtVoid Display(RtConstToken name, RtConstToken type,
  403                             RtConstToken mode, const ParamList& pList) {}
  404         virtual RtVoid Hider(RtConstToken name, const ParamList& pList) {}
  405         // ColorSamples is tested
  406         virtual RtVoid ColorSamples(const FloatArray& nRGB,
  407                             const FloatArray& RGBn);
  408         virtual RtVoid RelativeDetail(RtFloat relativedetail) {}
  409         // Option is tested
  410         virtual RtVoid Option(RtConstToken name, const ParamList& pList);
  411         virtual RtVoid AttributeBegin() {}
  412         virtual RtVoid AttributeEnd() {}
  413         // Color is tested
  414         virtual RtVoid Color(RtConstColor Cq);
  415         virtual RtVoid Opacity(RtConstColor Os) {}
  416         virtual RtVoid TextureCoordinates(RtFloat s1, RtFloat t1, RtFloat s2,
  417                             RtFloat t2, RtFloat s3, RtFloat t3, RtFloat s4,
  418                             RtFloat t4) {}
  419         // LightSource is tested
  420         virtual RtVoid LightSource(RtConstToken shadername, RtConstToken name,
  421                             const ParamList& pList);
  422         virtual RtVoid AreaLightSource(RtConstToken shadername,
  423                             RtConstToken name, const ParamList& pList) {}
  424         // Illuminate is tested
  425         virtual RtVoid Illuminate(RtConstToken name, RtBoolean onoff);
  426         virtual RtVoid Surface(RtConstToken name, const ParamList& pList) {}
  427         virtual RtVoid Displacement(RtConstToken name,
  428                             const ParamList& pList) {}
  429         virtual RtVoid Atmosphere(RtConstToken name, const ParamList& pList) {}
  430         virtual RtVoid Interior(RtConstToken name, const ParamList& pList) {}
  431         virtual RtVoid Exterior(RtConstToken name, const ParamList& pList) {}
  432         virtual RtVoid ShaderLayer(RtConstToken type, RtConstToken name,
  433                             RtConstToken layername, const ParamList& pList) {}
  434         virtual RtVoid ConnectShaderLayers(RtConstToken type,
  435                             RtConstToken layer1, RtConstToken variable1,
  436                             RtConstToken layer2, RtConstToken variable2) {}
  437         virtual RtVoid ShadingRate(RtFloat size) {}
  438         virtual RtVoid ShadingInterpolation(RtConstToken type) {}
  439         virtual RtVoid Matte(RtBoolean onoff) {}
  440         virtual RtVoid Bound(RtConstBound bound) {}
  441         virtual RtVoid Detail(RtConstBound bound) {}
  442         virtual RtVoid DetailRange(RtFloat offlow, RtFloat onlow,
  443                             RtFloat onhigh, RtFloat offhigh) {}
  444         virtual RtVoid GeometricApproximation(RtConstToken type,
  445                             RtFloat value) {}
  446         virtual RtVoid Orientation(RtConstToken orientation) {}
  447         virtual RtVoid ReverseOrientation() {}
  448         virtual RtVoid Sides(RtInt nsides) {}
  449         virtual RtVoid Identity() {}
  450         // Transform is tested
  451         virtual RtVoid Transform(RtConstMatrix transform);
  452         virtual RtVoid ConcatTransform(RtConstMatrix transform) {}
  453         virtual RtVoid Perspective(RtFloat fov) {}
  454         virtual RtVoid Translate(RtFloat dx, RtFloat dy, RtFloat dz) {}
  455         virtual RtVoid Rotate(RtFloat angle, RtFloat dx, RtFloat dy,
  456                             RtFloat dz) {}
  457         virtual RtVoid Scale(RtFloat sx, RtFloat sy, RtFloat sz) {}
  458         virtual RtVoid Skew(RtFloat angle, RtFloat dx1, RtFloat dy1,
  459                             RtFloat dz1, RtFloat dx2, RtFloat dy2,
  460                             RtFloat dz2) {}
  461         virtual RtVoid CoordinateSystem(RtConstToken space) {}
  462         virtual RtVoid CoordSysTransform(RtConstToken space) {}
  463         virtual RtVoid TransformBegin() {}
  464         virtual RtVoid TransformEnd() {}
  465         virtual RtVoid Resource(RtConstToken handle, RtConstToken type,
  466                             const ParamList& pList) {}
  467         virtual RtVoid ResourceBegin() {}
  468         virtual RtVoid ResourceEnd() {}
  469         virtual RtVoid Attribute(RtConstToken name, const ParamList& pList) {}
  470         virtual RtVoid Polygon(const ParamList& pList) {}
  471         virtual RtVoid GeneralPolygon(const IntArray& nverts,
  472                             const ParamList& pList) {}
  473         virtual RtVoid PointsPolygons(const IntArray& nverts,
  474                             const IntArray& verts, const ParamList& pList) {}
  475         virtual RtVoid PointsGeneralPolygons(const IntArray& nloops,
  476                             const IntArray& nverts, const IntArray& verts,
  477                             const ParamList& pList) {}
  478         // Basis is tested
  479         virtual RtVoid Basis(RtConstBasis ubasis, RtInt ustep,
  480                             RtConstBasis vbasis, RtInt vstep);
  481         virtual RtVoid Patch(RtConstToken type, const ParamList& pList) {}
  482         virtual RtVoid PatchMesh(RtConstToken type, RtInt nu,
  483                             RtConstToken uwrap, RtInt nv, RtConstToken vwrap,
  484                             const ParamList& pList) {}
  485         virtual RtVoid NuPatch(RtInt nu, RtInt uorder, const FloatArray& uknot,
  486                             RtFloat umin, RtFloat umax, RtInt nv, RtInt vorder,
  487                             const FloatArray& vknot, RtFloat vmin, RtFloat vmax,
  488                             const ParamList& pList) {}
  489         virtual RtVoid TrimCurve(const IntArray& ncurves, const IntArray& order,
  490                             const FloatArray& knot, const FloatArray& min,
  491                             const FloatArray& max, const IntArray& n,
  492                             const FloatArray& u, const FloatArray& v,
  493                             const FloatArray& w) {}
  494         // SubdivisionMesh is tested
  495         virtual RtVoid SubdivisionMesh(RtConstToken scheme,
  496                             const IntArray& nvertices, const IntArray& vertices,
  497                             const TokenArray& tags, const IntArray& nargs,
  498                             const IntArray& intargs,
  499                             const FloatArray& floatargs,
  500                             const ParamList& pList);
  501         // Sphere is tested
  502         virtual RtVoid Sphere(RtFloat radius, RtFloat zmin, RtFloat zmax,
  503                             RtFloat thetamax, const ParamList& pList);
  504         virtual RtVoid Cone(RtFloat height, RtFloat radius, RtFloat thetamax,
  505                             const ParamList& pList) {}
  506         virtual RtVoid Cylinder(RtFloat radius, RtFloat zmin, RtFloat zmax,
  507                             RtFloat thetamax, const ParamList& pList) {}
  508         // Hyperboloid is tested
  509         virtual RtVoid Hyperboloid(RtConstPoint point1, RtConstPoint point2,
  510                             RtFloat thetamax, const ParamList& pList);
  511         virtual RtVoid Paraboloid(RtFloat rmax, RtFloat zmin, RtFloat zmax,
  512                             RtFloat thetamax, const ParamList& pList) {}
  513         virtual RtVoid Disk(RtFloat height, RtFloat radius, RtFloat thetamax,
  514                             const ParamList& pList) {}
  515         virtual RtVoid Torus(RtFloat majorrad, RtFloat minorrad, RtFloat phimin,
  516                             RtFloat phimax, RtFloat thetamax,
  517                             const ParamList& pList) {}
  518         // Points is tested
  519         virtual RtVoid Points(const ParamList& pList);
  520         virtual RtVoid Curves(RtConstToken type, const IntArray& nvertices,
  521                             RtConstToken wrap, const ParamList& pList) {}
  522         virtual RtVoid Blobby(RtInt nleaf, const IntArray& code,
  523                             const FloatArray& floats, const TokenArray& strings,
  524                             const ParamList& pList) {}
  525         // Procedural is tested
  526         virtual RtVoid Procedural(RtPointer data, RtConstBound bound,
  527                             RtProcSubdivFunc refineproc,
  528                             RtProcFreeFunc freeproc);
  529         virtual RtVoid Geometry(RtConstToken type, const ParamList& pList) {}
  530         virtual RtVoid SolidBegin(RtConstToken type) {}
  531         virtual RtVoid SolidEnd() {}
  532         // ObjectBegin is tested
  533         virtual RtVoid ObjectBegin(RtConstToken name);
  534         virtual RtVoid ObjectEnd() {}
  535         virtual RtVoid ObjectInstance(RtConstToken name) {}
  536         // MotionBegin is tested
  537         virtual RtVoid MotionBegin(const FloatArray& times);
  538         virtual RtVoid MotionEnd() {}
  539         virtual RtVoid MakeTexture(RtConstString imagefile,
  540                             RtConstString texturefile, RtConstToken swrap,
  541                             RtConstToken twrap, RtFilterFunc filterfunc,
  542                             RtFloat swidth, RtFloat twidth,
  543                             const ParamList& pList) {}
  544         virtual RtVoid MakeLatLongEnvironment(RtConstString imagefile,
  545                             RtConstString reflfile, RtFilterFunc filterfunc,
  546                             RtFloat swidth, RtFloat twidth,
  547                             const ParamList& pList) {}
  548         virtual RtVoid MakeCubeFaceEnvironment(RtConstString px,
  549                             RtConstString nx, RtConstString py,
  550                             RtConstString ny, RtConstString pz,
  551                             RtConstString nz, RtConstString reflfile,
  552                             RtFloat fov, RtFilterFunc filterfunc,
  553                             RtFloat swidth, RtFloat twidth,
  554                             const ParamList& pList) {}
  555         virtual RtVoid MakeShadow(RtConstString picfile,
  556                             RtConstString shadowfile,
  557                             const ParamList& pList) {}
  558         // MakeOcclusion is tested
  559         virtual RtVoid MakeOcclusion(const StringArray& picfiles,
  560                             RtConstString shadowfile, const ParamList& pList);
  561         virtual RtVoid ErrorHandler(RtErrorFunc handler) {}
  562         virtual RtVoid ReadArchive(RtConstToken name,
  563                             RtArchiveCallback callback,
  564                             const ParamList& pList) {}
  565         virtual RtVoid ArchiveBegin(RtConstToken name,
  566                             const ParamList& pList) {}
  567         virtual RtVoid ArchiveEnd() {}
  568         //[[[end]]]
  569 
  570         virtual RtVoid ArchiveRecord(RtConstToken type, const char* string) {}
  571 };
  572 
  573 /// An error handler which throws MockRendererError
  574 class MockErrorHandler : public Ri::ErrorHandler
  575 {
  576     public:
  577         MockErrorHandler() : ErrorHandler(Warning) { }
  578 
  579     protected:
  580         virtual void dispatch(int code, const std::string& message)
  581         {
  582             throw MockRendererError(message);
  583         }
  584 };
  585 
  586 // Mock implementation of Ri::RendererServices
  587 class MockServices : public Ri::RendererServices
  588 {
  589     private:
  590         TokenDict m_tokenDict;
  591         MockErrorHandler m_errorHandler;
  592 
  593         friend RtVoid MockRenderer::Declare(RtConstString name,
  594                 RtConstString declaration);
  595     public:
  596         virtual ErrorHandler& errorHandler() { return m_errorHandler; }
  597         virtual RtFilterFunc     getFilterFunc(RtConstToken name) const {return &mockFilterFunc;}
  598         virtual RtConstBasis*    getBasis(RtConstToken name) const {return &g_mockBasis;}
  599         virtual RtErrorFunc      getErrorFunc(RtConstToken name) const {return 0;}
  600         virtual RtProcSubdivFunc getProcSubdivFunc(RtConstToken name) const {return &mockProcSubdivFunc;}
  601 
  602         virtual Ri::TypeSpec getDeclaration(RtConstToken token,
  603                                 const char** nameBegin = 0,
  604                                 const char** nameEnd = 0) const
  605         {
  606             return m_tokenDict.lookup(token, nameBegin, nameEnd);
  607         }
  608 
  609         void addFilter(const char* name, const Ri::ParamList& filterParams)
  610         { }
  611         virtual void addFilter(Ri::Filter& filter)
  612         { }
  613 
  614         Ri::Renderer& firstFilter()
  615         {
  616             // Wow, how awful!
  617             return *(Ri::Renderer*)0;
  618         }
  619 
  620         void parseRib(std::istream& ribStream, const char* name,
  621                       Ri::Renderer& context)
  622         { }
  623 };
  624 
  625 
  626 struct Fixture;
  627 static Fixture* g_fixture = 0;
  628 
  629 // Fixture for all tests.
  630 //
  631 // Insert tokens into the RIB stream using operator<<
  632 struct Fixture
  633 {
  634     MockRenderer renderer;
  635     MockServices services;
  636     TokenVec tokens;
  637     RibParserImpl parser;  //< to test.
  638     int checkPos;
  639 
  640     Fixture(int checkPosOffset = 0)
  641         : renderer(),
  642         tokens(),
  643         parser(services),
  644         checkPos(checkPosOffset)
  645     {
  646         g_fixture = this;
  647     }
  648 
  649     ~Fixture()
  650     {
  651         std::stringstream ribStream;
  652         for(int i = 0; i < (int)tokens.size(); ++i)
  653             ribStream << tokens[i] << " ";
  654         parser.parseStream(ribStream, "test_stream", renderer);
  655         BOOST_CHECK_EQUAL(checkPos, (int)tokens.size());
  656         g_fixture = 0;
  657     }
  658 
  659     template<typename T>
  660     Fixture& operator<<(const T& tok)
  661     {
  662         tokens.push_back(MockRibToken(tok));
  663         return *this;
  664     }
  665 };
  666 
  667 struct StringOrInt
  668 {
  669     const char* str;
  670     StringOrInt(const char* str) : str(str) {}
  671 };
  672 
  673 // A checker for request parameters
  674 //
  675 // This uses the tokens stored g_fixture to check the parameters which are
  676 // passed out into an interface call.
  677 struct CheckParams
  678 {
  679     private:
  680         // Dictionary of standard tokens.
  681         static TokenDict m_tokenDict;
  682 
  683         void nextParam() { ++g_fixture->checkPos; }
  684 
  685     public:
  686         CheckParams()
  687         {
  688             BOOST_REQUIRE(g_fixture);
  689         }
  690 
  691         CheckParams& operator<<(const IgnoreType&)
  692         {
  693             nextParam();
  694             return *this;
  695         }
  696         template<typename T>
  697         CheckParams& operator<<(const T& tok)
  698         {
  699             BOOST_CHECK_EQUAL(g_fixture->tokens.at(g_fixture->checkPos),
  700                               MockRibToken(tok));
  701             nextParam();
  702             return *this;
  703         }
  704         CheckParams& operator<<(const StringOrInt tok)
  705         {
  706             const MockRibToken t = g_fixture->tokens.at(g_fixture->checkPos);
  707             if(t.type() == Type_Int)
  708                 BOOST_CHECK_EQUAL(MockRibToken(std::atoi(tok.str)), t);
  709             else
  710                 BOOST_CHECK_EQUAL(MockRibToken(tok.str), t);
  711             nextParam();
  712             return *this;
  713         }
  714         CheckParams& operator<<(const Ri::ParamList& pList)
  715         {
  716             for(int i = 0; i < (int)pList.size(); ++i)
  717             {
  718                 try
  719                 {
  720                     const char* name = 0;
  721                     Ri::TypeSpec spec = m_tokenDict.lookup(
  722                             g_fixture->tokens.at(g_fixture->checkPos)
  723                             .getString().c_str(), &name);
  724                     BOOST_CHECK_EQUAL(spec, pList[i].spec());
  725                     BOOST_CHECK_EQUAL(name, pList[i].name());
  726                 }
  727                 catch(XqValidation& /*e*/)
  728                 {
  729                     // Intentionally blank for now, since it's tricky to test
  730                     // the custom-defined tokens.
  731                 }
  732                 nextParam();
  733                 BOOST_CHECK_EQUAL(g_fixture->tokens.at(g_fixture->checkPos),
  734                                   pList[i]);
  735                 nextParam();
  736             }
  737             return *this;
  738         }
  739 };
  740 TokenDict CheckParams::m_tokenDict;
  741 
  742 } // anon. namespace
  743 
  744 //------------------------------------------------------------------------------
  745 // Actual test cases
  746 //------------------------------------------------------------------------------
  747 // Tests for handler functions with hand-written implementations.
  748 
  749 BOOST_AUTO_TEST_CASE(RIB_version_test)
  750 {
  751     // Test the RIB-only version token... this doesn't actually do anything
  752     // right now but shouldn't generate an error
  753     Fixture(2) << Req("version") << 3.03f;
  754 }
  755 
  756 //--------------------------------------------------
  757 RtVoid MockRenderer::Declare(RtConstString name, RtConstString declaration)
  758 {
  759     CheckParams() << Req("Declare") << name << declaration;
  760     // UGH!
  761     g_fixture->services.m_tokenDict.declare(name, declaration);
  762 }
  763 BOOST_AUTO_TEST_CASE(Declare_handler_test)
  764 {
  765     // (Note: this test depends on MockRenderer::Sphere as well)
  766     Fixture() << Req("Declare") << "asdf" << "uniform float"
  767         << Req("Sphere") << 1.0f << -1.0f << 1.0f << 360.0f
  768             << "asdf" << std::vector<float>(1, 42.0f);
  769 }
  770 
  771 //--------------------------------------------------
  772 RtVoid MockRenderer::DepthOfField(RtFloat fstop, RtFloat focallength,
  773                                   RtFloat focaldistance)
  774 {
  775     CheckParams() << Req("DepthOfField");
  776     if(fstop == FLT_MAX)
  777     {
  778         BOOST_CHECK_EQUAL(focallength, FLT_MAX);
  779         BOOST_CHECK_EQUAL(focaldistance, FLT_MAX);
  780     }
  781     else
  782     {
  783         CheckParams() << fstop << focallength << focaldistance;
  784     }
  785 }
  786 BOOST_AUTO_TEST_CASE(DepthOfField_three_args_test)
  787 {
  788     Fixture() << Req("DepthOfField") << 1.0f << 42.0f << 42.5f;
  789 }
  790 BOOST_AUTO_TEST_CASE(DepthOfField_no_args_test)
  791 {
  792     Fixture() << Req("DepthOfField");
  793 }
  794 
  795 
  796 //--------------------------------------------------
  797 RtVoid MockRenderer::ColorSamples(const FloatArray& nRGB,
  798                                   const FloatArray& RGBn)
  799 {
  800     CheckParams() << Req("ColorSamples") << nRGB << RGBn;
  801 }
  802 BOOST_AUTO_TEST_CASE(ColorSamples_handler_test)
  803 {
  804     Fixture() << Req("ColorSamples") << std::vector<float>(12, 1.0f)
  805         << std::vector<float>(12, 1.0f);
  806 }
  807 
  808 
  809 //--------------------------------------------------
  810 RtVoid MockRenderer::LightSource(RtConstToken shadername,
  811                                         RtConstToken name,
  812                                         const ParamList& pList)
  813 {
  814     CheckParams() << Req("LightSource") << shadername
  815         << StringOrInt(name) << pList;
  816 }
  817 BOOST_AUTO_TEST_CASE(LightSource_integer_id_test)
  818 {
  819     // Test integer light identifiers
  820     Fixture() << Req("LightSource") << "blahlight" << 10;
  821 }
  822 BOOST_AUTO_TEST_CASE(LightSource_string_id_test)
  823 {
  824     // Test string light identifiers
  825     Fixture() << Req("LightSource") << "blahlight" << "stringName";
  826 }
  827 
  828 
  829 //--------------------------------------------------
  830 RtVoid MockRenderer::Illuminate(RtConstToken name, RtBoolean onoff)
  831 {
  832     CheckParams() << Req("Illuminate") << StringOrInt(name)
  833         << static_cast<int>(onoff);
  834 }
  835 BOOST_AUTO_TEST_CASE(Illuminate_handler_test)
  836 {
  837     Fixture()
  838         << Req("LightSource") << "blahlight" << 10
  839         << Req("LightSource") << "asdflight" << 11
  840         << Req("LightSource") << "qwerlight" << "handleName"
  841         << Req("Illuminate")  << 11 << 1
  842         << Req("Illuminate")  << 10 << 0
  843         << Req("Illuminate")  << "handleName" << 0;
  844 }
  845 
  846 
  847 //--------------------------------------------------
  848 RtVoid MockRenderer::Basis(RtConstBasis ubasis, RtInt ustep,
  849                            RtConstBasis vbasis, RtInt vstep)
  850 {
  851     BOOST_CHECK_EQUAL(g_mockBasis, ubasis);
  852     const float* vbStart = reinterpret_cast<const float*>(vbasis);
  853     CheckParams() << Req("Basis")
  854         << IgnoreParam << ustep <<
  855         std::vector<float>(vbStart, vbStart+16) << vstep;
  856 }
  857 BOOST_AUTO_TEST_CASE(Basis_handler_test)
  858 {
  859     Fixture() << Req("Basis") << "b-spline"
  860         << 1 << std::vector<float>(16, 2.0f) << 42;
  861 
  862 }
  863 
  864 
  865 //--------------------------------------------------
  866 RtVoid MockRenderer::SubdivisionMesh(RtConstToken scheme,
  867                                      const IntArray& nvertices,
  868                                      const IntArray& vertices,
  869                                      const TokenArray& tags,
  870                                      const IntArray& nargs,
  871                                      const IntArray& intargs,
  872                                      const FloatArray& floatargs,
  873                                      const ParamList& pList)
  874 {
  875     CheckParams() << Req("SubdivisionMesh")
  876         << scheme << nvertices << vertices
  877         << tags << nargs << intargs << floatargs << pList;
  878 }
  879 
  880 BOOST_AUTO_TEST_CASE(SubdivisionMesh_test)
  881 {
  882     std::vector<int> nvertices, vertices, nargs, intargs;
  883     std::vector<float> floatargs, P;
  884     std::vector<std::string> tags;
  885 
  886     nvertices += 4, 4;
  887     vertices += 0, 1, 4, 3,
  888                 1, 2, 5, 4;
  889     tags += "interpolateboundary", "crease";
  890     nargs += 0, 0,  2, 1;
  891     intargs += 1, 4;
  892     floatargs += 2.5f;
  893 
  894     P += -1, -1, 0,
  895           0, -1, 0,
  896           1, -1, 0,
  897          -1,  1, 0,
  898           0,  1, 0,
  899           1,  1, 0;
  900 
  901     // Full form
  902     Fixture() << Req("SubdivisionMesh")
  903         << "catmull-clark" << nvertices << vertices << tags << nargs
  904         << intargs << floatargs << "P" << P;
  905 
  906     // Abbreviated form
  907     Fixture() << Req("SubdivisionMesh")
  908         << "catmull-clark" << nvertices << vertices
  909         << IgnoreParam << IgnoreParam << IgnoreParam << IgnoreParam
  910         << "P" << P;
  911 }
  912 
  913 
  914 //--------------------------------------------------
  915 RtVoid MockRenderer::Hyperboloid(RtConstPoint point1, RtConstPoint point2,
  916                                  RtFloat thetamax, const ParamList& pList)
  917 {
  918     CheckParams() << Req("Hyperboloid") << point1[0] << point1[1] << point1[2]
  919         << point2[0] << point2[1] << point2[2] << thetamax
  920         << pList;
  921 }
  922 BOOST_AUTO_TEST_CASE(Hyperboloid_handler_test)
  923 {
  924     Fixture() << Req("Hyperboloid") << 1.0f << 2.0f << 3.0f
  925         << 4.0f << 5.0f << 6.0f << 360.0f;
  926 }
  927 
  928 
  929 //--------------------------------------------------
  930 RtVoid MockRenderer::Procedural(RtPointer data, RtConstBound bound,
  931                                 RtProcSubdivFunc refineproc,
  932                                 RtProcFreeFunc freeproc)
  933 {
  934     // The following checking is specific to the ProcRunProgram procedural.
  935     BOOST_CHECK_EQUAL(refineproc, mockProcSubdivFunc);
  936 
  937     // The following checking is valid for ProcRunProgram and ProcDynamicLoad
  938     const char** dataArray = reinterpret_cast<const char**>(data);
  939     const float* boundArray = reinterpret_cast<const float*>(bound);
  940     CheckParams() << Req("Procedural") << IgnoreParam
  941         << std::vector<std::string>(dataArray, dataArray+2)
  942         << std::vector<float>(boundArray, boundArray+6);
  943 }
  944 BOOST_AUTO_TEST_CASE(Procedural_handler_test)
  945 {
  946     std::vector<std::string> args; args += "progname", "some arg string";
  947     Fixture() << Req("Procedural") << "RunProgram"
  948         << args << std::vector<float>(6,1.0f);
  949 }
  950 
  951 
  952 //--------------------------------------------------
  953 RtVoid MockRenderer::ObjectBegin(RtConstToken name)
  954 {
  955     CheckParams() << Req("ObjectBegin")
  956         << StringOrInt(name);
  957 }
  958 BOOST_AUTO_TEST_CASE(ObjectBegin_integer_id_test)
  959 {
  960     Fixture() << Req("ObjectBegin") << 42;
  961 }
  962 BOOST_AUTO_TEST_CASE(ObjectBegin_string_id_test)
  963 {
  964     Fixture() << Req("ObjectBegin") << "a_string_handle";
  965 }
  966 BOOST_AUTO_TEST_CASE(ObjectBegin_bad_float_id_test)
  967 {
  968     BOOST_CHECK_THROW(
  969         Fixture() << Req("ObjectBegin") << 42.5f,
  970         MockRendererError
  971     );
  972 }
  973 
  974 
  975 //------------------------------------------------------------------------------
  976 // Tests for some of the autogenerated handler implementations.  Full test
  977 // coverage would be quite a burden (there's almost 100 interface functions!),
  978 // so only a few are tested here.
  979 //
  980 // The choices try to cover all Rt parameter types, and all cases where the
  981 // request handler has to do something special or unusual.
  982 
  983 //--------------------------------------------------
  984 RtVoid MockRenderer::Sphere(RtFloat radius, RtFloat zmin, RtFloat zmax,
  985                             RtFloat thetamax, const ParamList& pList)
  986 {
  987     CheckParams() << Req("Sphere") << radius << zmin << zmax << thetamax << pList;
  988 }
  989 BOOST_AUTO_TEST_CASE(Sphere_handler_test)
  990 {
  991     // Test RiSphere; also test the handling of valid parameter lists.
  992     Fixture() << Req("Sphere") << 2.5f << -1.0f << 1.0f << 360.0f
  993         << "uniform float blah" << std::vector<float>(2, 42.25f)
  994         << "Cs" << std::vector<float>(4, 2.0f);
  995 }
  996 
  997 
  998 //--------------------------------------------------
  999 RtVoid MockRenderer::Color(RtConstColor col)
 1000 {
 1001     CheckParams() << Req("Color") << col[0] << col[1] << col[2];
 1002 }
 1003 BOOST_AUTO_TEST_CASE(Color_handler_test)
 1004 {
 1005     Fixture() << Req("Color") << 1.0f << 2.0f << 3.0f;
 1006 }
 1007 
 1008 
 1009 //--------------------------------------------------
 1010 RtVoid MockRenderer::PixelFilter(RtFilterFunc function, RtFloat xwidth,
 1011                                  RtFloat ywidth)
 1012 {
 1013     BOOST_CHECK_EQUAL(function, mockFilterFunc);
 1014     CheckParams() << Req("PixelFilter") << IgnoreParam << xwidth << ywidth;
 1015 }
 1016 BOOST_AUTO_TEST_CASE(PixelFilter_handler_test)
 1017 {
 1018     Fixture() << Req("PixelFilter") << "sinc" << 7.0f << 7.5f;
 1019 }
 1020 
 1021 
 1022 //--------------------------------------------------
 1023 RtVoid MockRenderer::Transform(RtConstMatrix transform)
 1024 {
 1025     const float* trans = reinterpret_cast<const float*>(transform);
 1026     CheckParams() << Req("Transform")
 1027         << std::vector<float>(trans, trans+16);
 1028 }
 1029 BOOST_AUTO_TEST_CASE(Transform_handler_test)
 1030 {
 1031     float trans[16] = {
 1032         1,2,3,4,
 1033         5,6,7,8,
 1034         9,-1,-2,-3,
 1035         -4,-5,-6,-7
 1036     };
 1037 
 1038     Fixture() << Req("Transform")
 1039         << std::vector<float>(trans, trans+16);
 1040 }
 1041 
 1042 
 1043 //--------------------------------------------------
 1044 RtVoid MockRenderer::Points(const ParamList& pList)
 1045 {
 1046     CheckParams() << Req("Points") << pList;
 1047 }
 1048 BOOST_AUTO_TEST_CASE(Points_handler_test)
 1049 {
 1050     Fixture() << Req("Points")
 1051         << "Cs" << std::vector<float>(12, 0.5f)
 1052         << "P" << std::vector<float>(12, 1.5f);
 1053 }
 1054 
 1055 
 1056 //--------------------------------------------------
 1057 RtVoid MockRenderer::MotionBegin(const FloatArray& times)
 1058 {
 1059     CheckParams() << Req("MotionBegin") << times;
 1060 }
 1061 BOOST_AUTO_TEST_CASE(MotionBegin_handler_test)
 1062 {
 1063     std::vector<float> times;
 1064     times += 0, 1, 2.5, 3, 4;
 1065     Fixture() << Req("MotionBegin") << times;
 1066 }
 1067 
 1068 
 1069 //--------------------------------------------------
 1070 RtVoid MockRenderer::MakeOcclusion(const StringArray& picfiles,
 1071                                    RtConstString shadowfile,
 1072                                    const ParamList& pList)
 1073 {
 1074     CheckParams() << Req("MakeOcclusion") << picfiles << shadowfile << pList;
 1075 }
 1076 BOOST_AUTO_TEST_CASE(MakeOcclusion_handler_test)
 1077 {
 1078     std::vector<std::string> picFiles;
 1079     picFiles += "pic1", "pic2", "pic3", "some_pic4", "asdf5", "Occlmap6.om";
 1080     Fixture() << Req("MakeOcclusion") << picFiles << "ambient.map";
 1081 }
 1082 
 1083 
 1084 //------------------------------------------------------------------------------
 1085 // Test for parameter list handling, using RiOption as a proxy.
 1086 //
 1087 RtVoid MockRenderer::Option(RtConstToken name, const ParamList& pList)
 1088 {
 1089     CheckParams() << Req("Option") << name << pList;
 1090     // Check that the parameter list token count is correct.  Note that the
 1091     // formula used below assumes there's only one Req in the token stream.
 1092     BOOST_CHECK_EQUAL(2*pList.size(), g_fixture->tokens.size() - 2);
 1093 }
 1094 
 1095 
 1096 BOOST_AUTO_TEST_CASE(paramlist_int_array_value_test)
 1097 {
 1098     Fixture() << Req("Option") << "some_option_name"
 1099         << "uniform int asdf" << std::vector<int>(10, 42);
 1100 }
 1101 BOOST_AUTO_TEST_CASE(paramlist_float_array_value_test)
 1102 {
 1103     Fixture() << Req("Option") << "some_option_name"
 1104         << "uniform float asdf" << std::vector<float>(10, 2.5f);
 1105 }
 1106 BOOST_AUTO_TEST_CASE(paramlist_string_array_value_test)
 1107 {
 1108     Fixture() << Req("Option") << "some_option_name"
 1109         << "uniform string asdf" << std::vector<std::string>(10, "asdf_value");
 1110 }
 1111 BOOST_AUTO_TEST_CASE(extended_paramlist_test)
 1112 {
 1113     // Check that many mixed params work fine.
 1114     Fixture() << Req("Option") << "some_option_name"
 1115         << "uniform int user_i" << std::vector<int>(1, 42)
 1116         << "uniform float user_f" << std::vector<float>(1, 2.5f)
 1117         << "uniform vector user_v" << std::vector<float>(3, 3.5f)
 1118         << "uniform matrix user_m" << std::vector<float>(16, 4.5f)
 1119         << "uniform string s1" << std::vector<std::string>(1, "blah")
 1120         << "uniform string s2" << std::vector<std::string>(1, "s2val")
 1121         << "uniform string s3" << std::vector<std::string>(1, "s3val")
 1122         << "uniform string s4" << std::vector<std::string>(1, "s4val");
 1123 }
 1124 
 1125 BOOST_AUTO_TEST_CASE(invalid_paramlist_unknown_primvar)
 1126 {
 1127     // Check that unknown primvar names throw.
 1128     BOOST_CHECK_THROW(
 1129         Fixture() << Req("Option") << "some_option_name"
 1130             << "asdf" << std::vector<float>(1, 42.25f),
 1131         MockRendererError
 1132     );
 1133 }
 1134 BOOST_AUTO_TEST_CASE(invalid_paramlist_invalid_primvar)
 1135 {
 1136     // Check that invalid primvar strings throw.
 1137     BOOST_CHECK_THROW(
 1138         Fixture() << Req("Option") << "some_option_name"
 1139             << "] bad_token" << std::vector<float>(1, 42.25f),
 1140         MockRendererError
 1141     );
 1142 }
 1143 BOOST_AUTO_TEST_CASE(invalid_paramlist_missing_token)
 1144 {
 1145     // check that a missing token throws.
 1146     BOOST_CHECK_THROW(
 1147         Fixture() << Req("Option") << "some_option_name"
 1148             << "P" << std::vector<float>(4, 42.25f)
 1149             << std::vector<int>(1, 42),
 1150         MockRendererError
 1151     );
 1152 }
 1153 
 1154 BOOST_AUTO_TEST_SUITE_END()
 1155 
 1156 // vi: set et: