Пример #1
0
static void
testValueHash()
{
    static_assert(VtIsHashable<int>(), "");
    static_assert(!VtIsHashable<_Unhashable>(), "");

    VtValue vHashable{1};
    VtValue vUnhashable{_Unhashable{}};

    // Test the dynamic hashability check.
    TF_AXIOM(vHashable.CanHash());
    TF_AXIOM(!vUnhashable.CanHash());

    {
        // Test that hashable types can hash without error.
        TfErrorMark m;
        vHashable.GetHash();
        TF_AXIOM(m.IsClean());
    }

    {
        // Test that unhashable types post an error when attempting to hash.
        TfErrorMark m;
        vUnhashable.GetHash();
        TF_AXIOM(!m.IsClean());
        m.Clear();
    }
}
Пример #2
0
static void
_ThreadTask(TfErrorTransport *transport)
{
    TfErrorMark m;
    printf("Thread issuing error\n");
    TF_RUNTIME_ERROR("Cross-thread transfer test error");
    TF_AXIOM(not m.IsClean());
    m.TransportTo(*transport);
    TF_AXIOM(m.IsClean());
}
Пример #3
0
SdfRelationshipSpecHandle
UsdRelationship::_CreateSpec(bool fallbackCustom) const
{
    UsdStage *stage = _GetStage();
    // Try to create a spec for editing either from the definition or from
    // copying existing spec info.
    TfErrorMark m;
    if (SdfRelationshipSpecHandle relSpec =
        stage->_CreateRelationshipSpecForEditing(*this)) {
        return relSpec;
    }

    // If creating the spec on the stage failed without issuing an error, that
    // means there was no existing authored scene description to go on (i.e. no
    // builtin info from prim type, and no existing authored spec).  Stamp a
    // spec with the provided default values.
    if (m.IsClean()) {
        SdfChangeBlock block;
        return SdfRelationshipSpec::New(
            stage->_CreatePrimSpecForEditing(GetPrimPath()),
            _PropName().GetString(),
            /* custom = */ fallbackCustom, SdfVariabilityUniform);
    }
    return TfNullPtr;
}
Пример #4
0
int main()
{
    TfErrorMark mark;

    CameraAndLightTest();

    TF_VERIFY(mark.IsClean());

    if (mark.IsClean()) {
        std::cout << "OK" << std::endl;
        return EXIT_SUCCESS;
    } else {
        std::cout << "FAILED" << std::endl;
        return EXIT_FAILURE;
    }
}
Пример #5
0
bool Tf_PyEvaluateWithErrorCheck(
    const std::string & expr, boost::python::object * obj)
{
    TfErrorMark m;
    *obj = TfPyEvaluate(expr);
    return m.IsClean();
}
Пример #6
0
static bool
Test_TfErrorThreadTransport()
{
    TfErrorTransport transport;
    printf("Creating TfErrorMark\n");
    TfErrorMark m;
    printf("Launching thread\n");
    tbb::tbb_thread t(boost::bind(_ThreadTask, &transport));
    TF_AXIOM(m.IsClean());
    t.join();
    printf("Thread completed, posting error.\n");
    TF_AXIOM(m.IsClean());
    transport.Post();
    TF_AXIOM(not m.IsClean());
    m.Clear();

    return true;
}
Пример #7
0
static bool
Test_TfType_MultipleInheritance()
{
    // Test TfType::GetAncestorTypes()'s error condition of
    // inconsistent multiple inheritance.  (We'd ideally test this from
    // Python, but Python prohibits you from even declaring hierarchies
    // like this to begin with.)

    TfErrorMark m;
    m.SetMark();

    vector<TfType> types;

    TF_AXIOM(m.IsClean());

    TfType::Find<Z>().GetAllAncestorTypes(&types);

    TF_AXIOM(!m.IsClean());
    m.Clear();

    return true;
}
Пример #8
0
int main(int argc, char *argv[])
{
    TfErrorMark mark;

    BasicTest(argc, argv);

    if (mark.IsClean()) {
        std::cout << "OK" << std::endl;
        return EXIT_SUCCESS;
    } else {
        std::cout << "FAILED" << std::endl;
        return EXIT_FAILURE;
    }
}
MStatus
UsdMayaUndoHelperCommand::doIt(const MArgList& /*args*/)
{
    if (!_dgModifierFunc) {
        _undoable = false;
        return MS::kFailure;
    }

    TfErrorMark errorMark;
    errorMark.SetMark();
    (*_dgModifierFunc)(_modifier);
    _dgModifierFunc = nullptr;
    _undoable = errorMark.IsClean();
    return MS::kSuccess;
}
Пример #10
0
static unsigned int
_TestPySetenvNoInit()
{
    // Test that calling TfPySetenv causes an error.

    unsigned int numErrors = 0;

    const string envName = "PY_TEST_ENV_NAME";
    const string envVal = "TestPySetenvNoInit";

    if (TfPyIsInitialized()) {
        numErrors += 1;
        printf("ERROR: Python should not yet be initialized.\n");
        return numErrors;
    }

    {
        TfErrorMark m;
        fprintf(stderr, "===== Expected Error =====\n");
        bool didSet = TfPySetenv(envName, envVal);
        fprintf(stderr, "=== End Expected Error ===\n");
        if (didSet) {
            numErrors += 1;
            printf("ERROR: Calling TfPySetenv with uninitialized Python "
                   "should return false.");
        }

        if (m.IsClean()) {
            numErrors += 1;
            printf("ERROR: Calling TfPySetenv with uninitialized Python "
                   "should produce an error.");
        }
        m.Clear();
    }

    if (TfPyIsInitialized()) {
        numErrors += 1;
        printf("ERROR: Python should not yet be initialized.\n");
        return numErrors;
    }

    numErrors += _CheckResultInEnv(envName, "");

    return numErrors;
}
Пример #11
0
static int
_HandleErrors(const TfErrorMark &m, bool success)
{
    if (!success)
        return 1;

    if (m.IsClean())
        return 0;

    int rc(100);
    for (TfErrorMark::Iterator i = m.GetBegin(); i != m.GetEnd(); ++i)
    {
        ++rc;
        cerr << "*** Error in " << i->GetSourceFileName()
             << "@line " << i->GetSourceLineNumber()
             << "\n    " << i->GetCommentary() << "\n";
    }

    return(rc);
}
Пример #12
0
static void testValue() {
    {
        // Test that we can create values holding non-streamable types. 
        _NotStreamable n;
        VtValue v(n);
        VtValue copy = v;
        copy = n;
    }

    {
        // Test that we can store non-default-constructible objects in VtValue.
        _NotDefaultConstructible n(123);
        VtValue v(n);
        VtValue copy = v;
        copy = n;
    }

    {
        VtValue v(Vt_TestEnumVal1);
        TF_AXIOM(TfStringify(v) == "Vt_TestEnumVal1");
        v = Vt_TestEnumVal2;
        TF_AXIOM(TfStringify(v) == "Vt_TestEnumVal2");
    }

    {
        // Test that floating-point values stream as expected.
        TF_AXIOM(TfStringify(VtValue(0.0)) == "0");
        TF_AXIOM(TfStringify(VtValue(3.14159)) == "3.14159");
        TF_AXIOM(TfStringify(VtValue(0.1)) == "0.1");
        TF_AXIOM(TfStringify(VtValue(-0.000001)) == "-0.000001");
        TF_AXIOM(TfStringify(
             VtValue(std::numeric_limits<double>::infinity())) == "inf");
        TF_AXIOM(TfStringify(
             VtValue(-std::numeric_limits<double>::infinity())) == "-inf");

        TF_AXIOM(TfStringify(VtValue(0.0f)) == "0");
        TF_AXIOM(TfStringify(VtValue(3.14159f)) == "3.14159");
        TF_AXIOM(TfStringify(VtValue(0.1f)) == "0.1");
        TF_AXIOM(TfStringify(VtValue(-0.000001f)) == "-0.000001");
        TF_AXIOM(TfStringify(
             VtValue(std::numeric_limits<float>::infinity())) == "inf");
        TF_AXIOM(TfStringify(
             VtValue(-std::numeric_limits<float>::infinity())) == "-inf");
    }

    VtValue v(1.234);
    if (!v.IsHolding<double>())
        die("IsHolding");
    
    if (v.Get<double>() != 1.234)
        die("Get");

    if (v.GetTypeid() != typeid(double))
        die("GetTypeid");

    if (v.GetType() != TfType::Find<double>())
        die("GetType for unregistered type");

    if (v.GetElementTypeid() != typeid(void))
        die("GetElementTypeid for non-shaped type");

    v = VtValue("hello world");
    if (v.GetElementTypeid() != typeid(void))
        die("GetElementTypeid for non-shaped, non-stack-held type");

    if (v.IsArrayValued())
        die("IsArrayValued for non-array type");

    // Now test with shaped case.
    v = VtValue(VtDoubleArray(9));
    if (v.GetElementTypeid() != typeid(double))
        die("GetElementTypeid");

    // Test casts...

    v = VtValue(2.345);
    if (!v.CanCast<double>())
        die("CanCast to same type");
    if (v != VtValue::Cast<double>(v))
        die("Cast to same type");

    v = VtValue(2.345);
    if (!v.CanCast<int>())
        die("CanCast double to int");
    if (v.Cast<int>() != 2)
        die("Cast double to int");

    v = VtValue(2.345);
    if (!v.CanCast<short>())
        die("CanCast double to short");
    if (v.Cast<short>() != short(2))
        die("Cast double to short");

    v = VtValue(1.25);
    if (!v.CanCast<float>())
        die("CanCast double to float");
    if (v.Cast<float>() != 1.25f)
        die("Cast double to float");

    v = VtValue(1.25);
    if (v.CanCast<GfVec3d>())
        die("CanCast double to Vec3d");
    if (!v.Cast<GfVec3d>().IsEmpty())
        die("Cast to Vec3d type is not empty");

    v = VtValue(1.25);
    if (!v.CanCastToTypeOf(v))
        die("CanCast to same type");
    if (v.CastToTypeOf(v).Get<double>() != 1.25)
        die("Casting to same type got wrong value");
    
    v = VtValue(1.25);
    VtValue v2 = VtValue(3);
    if (!v.CanCastToTypeOf(v2))
        die("CanCast to type of another value");
    if (v2.CastToTypeOf(v).Get<double>() != 3.0)
        die("Could not cast to type of another value");

    v = VtValue(1.25);
    v2 = VtValue(3);
    if (!v.CanCastToTypeOf(v2))
        die("CanCast to type of another value");
    if (VtValue::CastToTypeOf(v2, v).Get<double>() != 3.0)
        die("Could not cast to type of another value");

    v = VtValue(1.25);
    if (!v.CanCastToTypeid(typeid(double)))
        die("CanCast to typeid of same type");
    if (!v.CanCastToTypeid(typeid(int)))
        die("CanCast double to typeid of int");
    if (v.CanCastToTypeid(typeid(GfVec3d)))
        die("CanCast double to typeid of GfVec3d");

    // Check that too large doubles cast to float infinities
    v = VtValue(1e50);
    if (!v.CanCast<float>())
        die("CanCast of too large double to float");
    if (v.Cast<float>() != std::numeric_limits<float>::infinity())
        die("Cast of too large double to float is not +inf");
    
    v = VtValue(-1e50);
    if (!v.CanCast<float>())
        die("CanCast of too small double to float");
    if (v.Cast<float>() != -std::numeric_limits<float>::infinity())
        die("Cast of too small double to float is not -inf");

    // Check that double infinities cast to float infinities
    v = VtValue(std::numeric_limits<double>::infinity());
    if (!v.CanCast<float>())
        die("CanCast of double +inf to float");
    if (v.Cast<float>() != std::numeric_limits<float>::infinity())
        die("Cast of double +inf to float is not +inf");

    v = VtValue(-std::numeric_limits<double>::infinity());
    if (!v.CanCast<float>())
        die("CanCast of double -inf to float");
    if (v.Cast<float>() != -std::numeric_limits<float>::infinity())
        die("Cast of double -inf to float is not -inf");

    // Check that float infinities cast to double infinities
    v = VtValue(std::numeric_limits<float>::infinity());
    if (!v.CanCast<double>())
        die("CanCast of float +inf to double");
    if (v.Cast<double>() != std::numeric_limits<double>::infinity())
        die("Cast of float +inf to double is not +inf");

    v = VtValue(-std::numeric_limits<float>::infinity());
    if (!v.CanCast<double>())
        die("CanCast of float -inf to double");
    if (v.Cast<double>() != -std::numeric_limits<double>::infinity())
        die("Cast of float -inf to double is not -inf");

    // Check that really large long long casts to double
    v = VtValue(1000000000000000000ll);
    if (!v.CanCast<double>())
        die("CanCast of really large long long to double");
    if (v.Cast<double>() != 1e+18)
        die("Cast of really large long long to double");

    // Check that really large long long casts to float
    v = VtValue(1000000000000000000ll);
    if (!v.CanCast<float>())
        die("CanCast of really large long long to float");
    if (v.Cast<float>() != 1e+18f)
        die("Cast of really large long long to float");
        
    // Check that really large long long casts to GfHalf infinity
    v = VtValue(1000000000000000000ll);
    if (!v.CanCast<GfHalf>())
        die("CanCast of really large long long to GfHalf");
    if (v.Cast<GfHalf>() != std::numeric_limits<GfHalf>::infinity())
        die("Cast of really large long long to GfHalf is not +inf");

    // Check that really small long long casts to minus GfHalf infinity
    v = VtValue(-1000000000000000000ll);
    if (!v.CanCast<GfHalf>())
        die("CanCast of really small long long to GfHalf");
    if (v.Cast<GfHalf>() != -std::numeric_limits<GfHalf>::infinity())
        die("Cast of really small long long to GfHalf is not -inf");

    // Check that too large unsigned short casts to GfHalf infinity
    v = VtValue((unsigned short)65535);
    if (!v.CanCast<GfHalf>())
        die("CanCast of too large unsigned short to GfHalf");
    if (v.Cast<GfHalf>() != std::numeric_limits<GfHalf>::infinity())
        die("Cast of too large unsigned short to GfHalf is not +inf");

    // Some sanity checks
    v = VtValue((int)0);
    if (!v.CanCast<double>())
        die("CanCast of integer zero to double");
    if (v.Cast<double>() != 0.0)
        die("Cast of integer zero to double not zero");

    v = VtValue((int)-1);
    if (!v.CanCast<double>())
        die("CanCast of integer -1 to double");
    if (v.Cast<double>() != -1.0)
        die("Cast of integer -1 to double not -1");

    v = VtValue((int)+1);
    if (!v.CanCast<double>())
        die("CanCast of integer one to double");
    if (v.Cast<double>() != +1.0)
        die("Cast of integer one to double not one");

    // Range-checked casts.
    v = VtValue(std::numeric_limits<short>::max());
    v.Cast<short>();
    TF_AXIOM(v.IsHolding<short>() &&
             v.UncheckedGet<short>() == std::numeric_limits<short>::max());
    // Out-of-range should fail.
    v = VtValue(std::numeric_limits<int>::max());
    v.Cast<short>();
    TF_AXIOM(v.IsEmpty());

    v = VtValue(std::numeric_limits<unsigned int>::max());
    v.Cast<int>();
    TF_AXIOM(v.IsEmpty());

    // expected to succeed
    _TestVecCast<GfVec2h>(GfVec2i(1, 2));
    _TestVecCast<GfVec2f>(GfVec2i(1, 2));
    _TestVecCast<GfVec2d>(GfVec2i(1, 2));
    _TestVecCast<GfVec2f>(GfVec2h(1, 2));
    _TestVecCast<GfVec2d>(GfVec2h(1, 2));
    _TestVecCast<GfVec2d>(GfVec2f(1, 2));
    _TestVecCast<GfVec2h>(GfVec2f(1, 2));
    _TestVecCast<GfVec2h>(GfVec2d(1, 2));
    _TestVecCast<GfVec2f>(GfVec2d(1, 2));

    _TestVecCast<GfVec3h>(GfVec3i(1, 2, 3));
    _TestVecCast<GfVec3f>(GfVec3i(1, 2, 3));
    _TestVecCast<GfVec3d>(GfVec3i(1, 2, 3));
    _TestVecCast<GfVec3f>(GfVec3h(1, 2, 3));
    _TestVecCast<GfVec3d>(GfVec3h(1, 2, 3));
    _TestVecCast<GfVec3d>(GfVec3f(1, 2, 3));
    _TestVecCast<GfVec3h>(GfVec3f(1, 2, 3));
    _TestVecCast<GfVec3h>(GfVec3d(1, 2, 3));
    _TestVecCast<GfVec3f>(GfVec3d(1, 2, 3));

    _TestVecCast<GfVec4h>(GfVec4i(1, 2, 3, 4));
    _TestVecCast<GfVec4f>(GfVec4i(1, 2, 3, 4));
    _TestVecCast<GfVec4d>(GfVec4i(1, 2, 3, 4));
    _TestVecCast<GfVec4f>(GfVec4h(1, 2, 3, 4));
    _TestVecCast<GfVec4d>(GfVec4h(1, 2, 3, 4));
    _TestVecCast<GfVec4d>(GfVec4f(1, 2, 3, 4));
    _TestVecCast<GfVec4h>(GfVec4f(1, 2, 3, 4));
    _TestVecCast<GfVec4h>(GfVec4d(1, 2, 3, 4));
    _TestVecCast<GfVec4f>(GfVec4d(1, 2, 3, 4));

    _FailVecCast<GfVec4i>(GfVec4h(1, 2, 3, 4));
    _FailVecCast<GfVec4i>(GfVec4f(1, 2, 3, 4));
    _FailVecCast<GfVec4i>(GfVec4d(1, 2, 3, 4));

    _FailVecCast<GfVec3i>(GfVec3h(1, 2, 3));
    _FailVecCast<GfVec3i>(GfVec3f(1, 2, 3));
    _FailVecCast<GfVec3i>(GfVec3d(1, 2, 3));

    _FailVecCast<GfVec2i>(GfVec2h(1, 2));
    _FailVecCast<GfVec2i>(GfVec2f(1, 2));
    _FailVecCast<GfVec2i>(GfVec2d(1, 2));

    // Equality special cases.

    v = VtValue();
    v2 = VtValue();

    if (!(v == v2))
        die("comparison with empty");

    v = VtValue(1.234);

    if (v == v2)
        die("comparison with empty");

    v2 = VtValue("hello");

    if (v == v2)
        die("comparison of mismatched types");

    v = VtValue(1234.0);
    v2 = VtValue(1234);
    if (v == v2)
        die("comparison of mismatched stack-held types");

    // Coverage

    v = VtValue();
    if (v.IsArrayValued())
        die("IsArrayValued for empty value");

    v = VtValue(1.234);
    if (v.IsArrayValued())
        die("scalar value reports it is shaped");

    v = VtValue(VtDoubleArray());
    if (!v.IsArrayValued())
        die("array value reports it is not an array");


    // Streaming...
    VtDictionary d;
    d["foo"] = 1.234;
    d["bar"] = "baz";

    vector<VtValue> vals;
    vals.push_back(VtValue(1.234));
    vals.push_back(VtValue("hello world"));

    std::ostringstream stream;
    stream << VtValue(d);
    if (stream.str().empty())
        die("couldn't stream value holding dictionary.");

    std::ostringstream stream2;
    stream2 << VtValue(vals);
    if (stream2.str().empty())
        die("couldn't stream value holding vector of values.");


    // Default stuff...
    TF_AXIOM(VtDictionaryGet<double>(d, "foo", VtDefault = 0) == 1.234);
    TF_AXIOM(VtDictionaryGet<double>(d, "noKey", VtDefault = 3.14) == 3.14);
    TF_AXIOM(VtDictionaryGet<string>(d, "bar", VtDefault = "hello") == "baz");
    TF_AXIOM(VtDictionaryGet<string>(d, "noKey", VtDefault = "bye") == "bye");


    // Casting a VtValue holding a TfToken to a string.
    {
        TfToken token("token");
        VtValue val(token);
        TF_AXIOM(val.IsHolding<TfToken>());
        val.Cast<string>();
        TF_AXIOM(val.IsHolding<string>());
        TF_AXIOM(val.Get<string>() == "token");
    }

    // Assignment and equality with string literals.
    {
        VtValue val;
        val = "hello";
        TF_AXIOM(val.IsHolding<string>());
        TF_AXIOM(val.Get<string>() == "hello");
        TF_AXIOM(val == "hello");
        TF_AXIOM("hello" == val);
    }

    // Equality
    {
        double d = 1.234, e = 2.71828;
        VtValue v(d);
        TF_AXIOM(v == d);
        TF_AXIOM(d == v);
        TF_AXIOM(v != e);
        TF_AXIOM(e != v);
    }

    // IsHolding<VtValue>
    {
        VtValue v(1.234);
        TF_AXIOM(v.IsHolding<double>());
        TF_AXIOM(v.IsHolding<VtValue>());
    }

    // Shapeliness and other stuff with non-stack-held arrays.
    {
        VtVec2iArray a(2), b(3);
        VtValue v(a);
        VtValue vclone(v);
        TF_AXIOM(v.Get<VtVec2iArray>().size() == 2);
        v = b;
        TF_AXIOM(v.Get<VtVec2iArray>().size() == 3);
        TF_AXIOM(v.IsArrayValued());
        TF_AXIOM(v.GetElementTypeid() == typeid(GfVec2i));
        TF_AXIOM(vclone.Get<VtVec2iArray>().size() == 2);
    }

    // Precision-casting of VtArrays
    {
        // only testing float <-> double... compound Vec types should
        // be the same
        VtFloatArray  fa(3), fRoundTripped;
        VtDoubleArray  da;

        fa[0] = 1.23456567;
        fa[1] = 4.63256635;
        fa[2] = 123443634.432;

        VtValue  v(fa);
        v.Cast<VtDoubleArray>();
        TF_AXIOM(v.IsHolding<VtDoubleArray>());
        da = v.UncheckedGet<VtDoubleArray>();

        VtValue vv(da);
        vv.Cast<VtFloatArray>();
        TF_AXIOM(vv.IsHolding<VtFloatArray>());
        fRoundTripped = vv.UncheckedGet<VtFloatArray>();
        // verify they compare euqal, but are physically two different arrays
        TF_AXIOM(fRoundTripped == fa);
        TF_AXIOM(!fRoundTripped.IsIdentical(fa));
    }

    // Test swapping VtValues holding dictionaries.
    {
        VtValue a, b;
        VtDictionary d1, d2;

        d1["foo"] = "bar";
        d2["bar"] = "foo";

        a = d1;
        b = d2;

        a.Swap(b);

        TF_AXIOM(a.Get<VtDictionary>().count("bar"));
        TF_AXIOM(b.Get<VtDictionary>().count("foo"));
    }

    // Test creating VtValues by taking contents of objects, and destructively
    // removing contents from objects.
    {
        string s("hello world!");
        VtValue v = VtValue::Take(s);
        TF_AXIOM(s.empty());
        TF_AXIOM(v.IsHolding<string>());
        TF_AXIOM(v.UncheckedGet<string>() == "hello world!");
        v.Swap(s);
        TF_AXIOM(v.IsHolding<string>());
        TF_AXIOM(v.UncheckedGet<string>().empty());
        TF_AXIOM(s == "hello world!");
        
        v.Swap(s);
        TF_AXIOM(v.IsHolding<string>() &&
                 v.UncheckedGet<string>() == "hello world!");
        string t = v.Remove<string>();
        TF_AXIOM(t == "hello world!");
        TF_AXIOM(v.IsEmpty());

        v.Swap(t);
        TF_AXIOM(t.empty());
        TF_AXIOM(v.IsHolding<string>() &&
                 v.UncheckedGet<string>() == "hello world!");

        t = v.UncheckedRemove<string>();
        TF_AXIOM(t == "hello world!");
        TF_AXIOM(v.IsEmpty());
    }

    // Test calling Get with incorrect type.  Should issue an error and produce
    // some "default" value.

    {
        VtValue empty;
        TfErrorMark m;
        TF_AXIOM(empty.Get<bool>() == false);
        TF_AXIOM(!m.IsClean());
    }

    {
        VtValue d(1.234);
        TfErrorMark m;
        TF_AXIOM(d.Get<double>() == 1.234);
        TF_AXIOM(m.IsClean());

        m.SetMark();
        TF_AXIOM(d.Get<int>() == 0);
        TF_AXIOM(!m.IsClean());
        
        m.SetMark();
        TF_AXIOM(d.Get<string>() == string());
        TF_AXIOM(!m.IsClean());
    }

}
Пример #13
0
static bool
Test_TfError()
{

    TfErrorMark m;
    size_t lineNum;

    m.SetMark();
    TF_AXIOM(m.IsClean());

    m.SetMark();
    TF_ERROR(SMALL, "small error");
    lineNum = __LINE__ - 1;
    TF_AXIOM(!m.IsClean());

    TfErrorMark::Iterator i = m.GetBegin();
    TF_AXIOM(i == TfDiagnosticMgr::GetInstance().GetErrorBegin());
    TfError e = *i;
    TF_AXIOM(e.GetSourceFileName() == BUILD_COMPONENT_SRC_PREFIX __FILE__);
    TF_AXIOM(e.GetSourceLineNumber() == lineNum);
    TF_AXIOM(e.GetCommentary() == "small error");
    TF_AXIOM(e.GetErrorCode() == SMALL);
    TF_AXIOM(e.GetErrorCodeAsString() == "SMALL");
    TF_AXIOM(e.GetInfo<int>() == NULL);
    e.AugmentCommentary("augment");
    TF_AXIOM(e.GetCommentary() == "small error\naugment");
    i = TfDiagnosticMgr::GetInstance().EraseError(i);
    TF_AXIOM(i == TfDiagnosticMgr::GetInstance().GetErrorEnd());

    m.SetMark();
    TF_ERROR(1, MEDIUM, "medium error");
    TF_ERROR(2, LARGE, "large error");

    i = m.GetBegin();
    TF_AXIOM(i == TfDiagnosticMgr::GetInstance().GetErrorBegin());
    e = *i;
    TF_AXIOM(e.GetErrorCode() == MEDIUM);
    TF_AXIOM(*e.GetInfo<int>() == 1);

    ++i;
    TF_AXIOM(i != TfDiagnosticMgr::GetInstance().GetErrorEnd());
    e = *i;
    TF_AXIOM(e.GetErrorCode() == LARGE);
    TF_AXIOM(*e.GetInfo<int>() == 2);

    m.Clear();
    TF_AXIOM(m.IsClean());

    TF_VERIFY(m.IsClean());

    TF_AXIOM(TF_VERIFY(m.IsClean()));

    TF_CODING_ERROR("test error");

    // It should be the case that m is not clean.
    TF_AXIOM(TF_VERIFY(not m.IsClean()));

    // It should not be the case that m is clean.
    TF_AXIOM(not TF_VERIFY(m.IsClean()));

    TF_AXIOM(not TF_VERIFY(m.IsClean(), "With a %s", "message."));

    // Should issue a failed expect error.
    TF_VERIFY(m.IsClean());

    m.Clear();

    // Arbitrary info.
    std::string info("String containing arbitrary information.");

    // Issue a few different variations of errors.
    m.SetMark();

    string errString = "Error!";

    TF_CODING_ERROR("Coding error");
    TF_CODING_ERROR("Coding error %d", 1);
    TF_CODING_ERROR(errString);

    TF_RUNTIME_ERROR("Runtime error");
    TF_RUNTIME_ERROR("Runtime error %d", 1);
    TF_RUNTIME_ERROR(errString);

    TF_ERROR(SMALL, "const char *");
    TF_ERROR(SMALL, "const char *, %s", "...");
    TF_ERROR(SMALL, errString);

    TF_ERROR(info, MEDIUM, "const char *");
    TF_ERROR(info, MEDIUM, "const char *, %s", "...");
    TF_ERROR(info, MEDIUM, errString);

    TF_AXIOM(not m.IsClean());
    m.Clear();

    // Issue a few different warnings.
    string warningString = "Warning!";

    TF_WARN("const char *");
    TF_WARN("const char *, %s", "...");
    TF_WARN(warningString);

    TF_WARN(SMALL, "const char *");
    TF_WARN(SMALL, "const char *, %s", "...");
    TF_WARN(SMALL, warningString);

    TF_WARN(info, MEDIUM, "const char *");
    TF_WARN(info, MEDIUM, "const char *, %s", "...");
    TF_WARN(info, MEDIUM, warningString);

    // Issue a few different status messages.
    string statusString = "Status";

    TF_STATUS("const char *");
    TF_STATUS("const char *, %s", "...");
    TF_STATUS(statusString);

    TF_STATUS(SMALL, "const char *");
    TF_STATUS(SMALL, "const char *, %s", "...");
    TF_STATUS(SMALL, statusString);

    TF_STATUS(info, MEDIUM, "const char *");
    TF_STATUS(info, MEDIUM, "const char *, %s", "...");
    TF_STATUS(info, MEDIUM, statusString);

    return true;
}
void
My_TestGLDrawing::DrawTest(bool offscreen)
{
    std::cout << "My_TestGLDrawing::DrawTest()\n";

    HdPerfLog& perfLog = HdPerfLog::GetInstance();
    perfLog.Enable();
    
    // Reset all counters we care about.
    perfLog.ResetCache(HdTokens->extent);
    perfLog.ResetCache(HdTokens->points);
    perfLog.ResetCache(HdTokens->topology);
    perfLog.ResetCache(HdTokens->transform);
    perfLog.SetCounter(UsdImagingTokens->usdVaryingExtent, 0);
    perfLog.SetCounter(UsdImagingTokens->usdVaryingPrimvar, 0);
    perfLog.SetCounter(UsdImagingTokens->usdVaryingTopology, 0);
    perfLog.SetCounter(UsdImagingTokens->usdVaryingVisibility, 0);
    perfLog.SetCounter(UsdImagingTokens->usdVaryingXform, 0);

    int width = GetWidth(), height = GetHeight();

    double aspectRatio = double(width)/height;
    GfFrustum frustum;
    frustum.SetPerspective(60.0, aspectRatio, 1, 100000.0);

    GfMatrix4d viewMatrix;
    viewMatrix.SetIdentity();
    viewMatrix *= GfMatrix4d().SetRotate(GfRotation(GfVec3d(0, 1, 0), _rotate[0]));
    viewMatrix *= GfMatrix4d().SetRotate(GfRotation(GfVec3d(1, 0, 0), _rotate[1]));
    viewMatrix *= GfMatrix4d().SetTranslate(GfVec3d(_translate[0], _translate[1], _translate[2]));

    GfMatrix4d projMatrix = frustum.ComputeProjectionMatrix();

    GfMatrix4d modelViewMatrix = viewMatrix; 
    if (UsdGeomGetStageUpAxis(_stage) == UsdGeomTokens->z) {
        // rotate from z-up to y-up
        modelViewMatrix = 
            GfMatrix4d().SetRotate(GfRotation(GfVec3d(1.0,0.0,0.0), -90.0)) *
            modelViewMatrix;
    }

    GfVec4d viewport(0, 0, width, height);
    _engine->SetCameraState(modelViewMatrix, projMatrix, viewport);

    size_t i = 0;
    TF_FOR_ALL(timeIt, GetTimes()) {
        UsdTimeCode time = *timeIt;
        if (*timeIt == -999) {
            time = UsdTimeCode::Default();
        }
        UsdImagingGLRenderParams params;
        params.drawMode = GetDrawMode();
        params.enableLighting = IsEnabledTestLighting();
        params.enableIdRender = IsEnabledIdRender();
        params.frame = time;
        params.complexity = _GetComplexity();
        params.cullStyle = IsEnabledCullBackfaces() ?
                            UsdImagingGLCullStyle::CULL_STYLE_BACK :
                            UsdImagingGLCullStyle::CULL_STYLE_NOTHING;

        glViewport(0, 0, width, height);

        glEnable(GL_DEPTH_TEST);

        if(IsEnabledTestLighting()) {
            if(UsdImagingGLEngine::IsHydraEnabled()) {
                _engine->SetLightingState(_lightingContext);
            } else {
                _engine->SetLightingStateFromOpenGL();
            }
        }

        if (!GetClipPlanes().empty()) {
            params.clipPlanes = GetClipPlanes();
            for (size_t i=0; i<GetClipPlanes().size(); ++i) {
                glEnable(GL_CLIP_PLANE0 + i);
            }
        }

        GfVec4f const &clearColor = GetClearColor();
        GLfloat clearDepth[1] = { 1.0f };

        // Make sure we render to convergence.
        TfErrorMark mark;
        do {
            glClearBufferfv(GL_COLOR, 0, clearColor.data());
            glClearBufferfv(GL_DEPTH, 0, clearDepth);
            _engine->Render(_stage->GetPseudoRoot(), params);
        } while (!_engine->IsConverged());
        TF_VERIFY(mark.IsClean(), "Errors occurred while rendering!");

        std::cout << "itemsDrawn " << perfLog.GetCounter(HdTokens->itemsDrawn) << std::endl;
        std::cout << "totalItemCount " << perfLog.GetCounter(HdTokens->totalItemCount) << std::endl;

        std::string imageFilePath = GetOutputFilePath();
        if (!imageFilePath.empty()) {
            if (time != UsdTimeCode::Default()) {
                std::stringstream suffix;
                suffix << "_" << std::setw(3) << std::setfill('0') << params.frame << ".png";
                imageFilePath = TfStringReplace(imageFilePath, ".png", suffix.str());
            }
            std::cout << imageFilePath << "\n";
            WriteToFile("color", imageFilePath);
        }
        i++;
    }