void mediadataclient_object_t::test<7>()
{
    // Test LLMediaDataClient::isInQueue()
    LOG_TEST(7);

    LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(
        _DATA(VALID_OBJECT_ID_1,"3.0","true"));
    LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(
        _DATA(VALID_OBJECT_ID_2,"1.0","true"));
    int num_refs_start = o1->getNumRefs();
    {
        LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);

        ensure("not in queue yet 1", ! mdc->isInQueue(o1));
        ensure("not in queue yet 2", ! mdc->isInQueue(o2));

        mdc->fetchMedia(o1);

        ensure("is in queue", mdc->isInQueue(o1));
        ensure("is not in queue", ! mdc->isInQueue(o2));

        ::pump_timers();

        ensure("not in queue anymore", ! mdc->isInQueue(o1));
        ensure("still is not in queue", ! mdc->isInQueue(o2));

        ensure("queue empty", mdc->isEmpty());
    }

    // Make sure everyone's destroyed properly
    ensure("REF COUNT", o1->getNumRefs(), num_refs_start);

}
void mediadataclient_object_t::test<8>()
{
    // Test queue handling of objects that are marked dead.
    LOG_TEST(8);

    LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"4.0","true"));
    LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"3.0","true"));
    LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"2.0","true"));
    LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"1.0","true"));
    {
        LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);

        // queue up all 4 objects
        mdc->fetchMedia(o1);
        mdc->fetchMedia(o2);
        mdc->fetchMedia(o3);
        mdc->fetchMedia(o4);

        ensure("is in queue 1", mdc->isInQueue(o1));
        ensure("is in queue 2", mdc->isInQueue(o2));
        ensure("is in queue 3", mdc->isInQueue(o3));
        ensure("is in queue 4", mdc->isInQueue(o4));
        ensure("post records", gPostRecords->size(), 0);

        // and mark the second and fourth ones dead.  Call removeFromQueue when marking dead, since this is what LLVOVolume will do.
        dynamic_cast<LLMediaDataClientObjectTest*>(static_cast<LLMediaDataClientObject*>(o2))->markDead();
        mdc->removeFromQueue(o2);
        dynamic_cast<LLMediaDataClientObjectTest*>(static_cast<LLMediaDataClientObject*>(o4))->markDead();
        mdc->removeFromQueue(o4);

        // The removeFromQueue calls should remove the second and fourth ones
        ensure("is in queue 1", mdc->isInQueue(o1));
        ensure("is not in queue 2", !mdc->isInQueue(o2));
        ensure("is in queue 3", mdc->isInQueue(o3));
        ensure("is not in queue 4", !mdc->isInQueue(o4));
        ensure("post records", gPostRecords->size(), 0);

        ::pump_timers();

        // The first tick should process the first item
        ensure("is not in queue 1", !mdc->isInQueue(o1));
        ensure("is not in queue 2", !mdc->isInQueue(o2));
        ensure("is in queue 3", mdc->isInQueue(o3));
        ensure("is not in queue 4", !mdc->isInQueue(o4));
        ensure("post records", gPostRecords->size(), 1);

        ::pump_timers();

        // The second tick should process the third, emptying the queue
        ensure("is not in queue 3", !mdc->isInQueue(o3));
        ensure("post records", gPostRecords->size(), 2);

        ensure("queue empty", mdc->isEmpty());
    }
    ensure("refcount of o1", o1->getNumRefs(), 1);
    ensure("refcount of o2", o2->getNumRefs(), 1);
    ensure("refcount of o3", o3->getNumRefs(), 1);
    ensure("refcount of o4", o4->getNumRefs(), 1);

}
void mediadataclient_object_t::test<6>()
{
    //
    // Test navigate() with a bounce back
    //
    LOG_TEST(6);

    LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(
        _DATA_URLS(VALID_OBJECT_ID,
                   "1.0","true",
                   FAKE_OBJECT_MEDIA_CAP_URL,
                   FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR));
    {
        LLPointer<LLObjectMediaNavigateClient> mdc = new LLObjectMediaNavigateClient(NO_PERIOD,NO_PERIOD);
        const char *TEST_URL = "http://example.com";
        mdc->navigate(o, 0, TEST_URL);
        ensure("post records", gPostRecords->size(), 0);
        ::pump_timers();

        // ensure bounce back
        ensure("bounce back",
               dynamic_cast<LLMediaDataClientObjectTest*>(static_cast<LLMediaDataClientObject*>(o))->getNumBounceBacks(),
               1);

        ensure("post records", gPostRecords->size(), 1);
        ensure("post url", (*gPostRecords)[0]["url"], FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR);
        ensure("post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID));
        ensure("post data", (*gPostRecords)[0]["body"][LLTextureEntry::TEXTURE_INDEX_KEY], 0);
        ensure("post data", (*gPostRecords)[0]["body"][LLMediaEntry::CURRENT_URL_KEY], TEST_URL);
        ensure("queue empty", mdc->isEmpty());
    }
    ensure("REF COUNT", o->getNumRefs(), 1);
}
void mediadataclient_object_t::test<2>()
{
    //
    // Test updateMedia()
    //
    LOG_TEST(2);

    LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(DATA);
    {
        // queue time w/ no delay ensures that ::pump_timers() will hit the tick()
        LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
        mdc->updateMedia(o);
        ensure("post records", gPostRecords->size(), 0);
        ::pump_timers();

        ensure("post records", gPostRecords->size(), 1);
        ensure("post url", (*gPostRecords)[0]["url"], FAKE_OBJECT_MEDIA_CAP_URL);
        ensure("post UPDATE", (*gPostRecords)[0]["body"]["verb"], "UPDATE");
        ensure("post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID));
        ensure_llsd("post data llsd", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_MEDIA_DATA_KEY],
                    "<llsd>" MEDIA_DATA "</llsd>");
        ensure("queue empty", mdc->isEmpty());
    }

    ensure("REF COUNT", o->getNumRefs(), 1);
}
void mediadataclient_object_t::test<1>()
{
    //
    // Test fetchMedia()
    //
    LOG_TEST(1);

    LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(DATA);
    int num_refs_start = o->getNumRefs();
    {
        LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
        mdc->fetchMedia(o);

        // Make sure no posts happened yet...
        ensure("post records", gPostRecords->size(), 0);

        ::pump_timers();

        ensure("post records", gPostRecords->size(), 1);
        ensure("post url", (*gPostRecords)[0]["url"], FAKE_OBJECT_MEDIA_CAP_URL);
        ensure("post GET", (*gPostRecords)[0]["body"]["verb"], "GET");
        ensure("post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID));
        ensure("queue empty", mdc->isEmpty());
    }

    // Make sure everyone's destroyed properly
    ensure("REF COUNT", o->getNumRefs(), num_refs_start);
}
void mediadataclient_object_t::test<5>()
{
    //
    // Test fetchMedia() getting a 503 error
    //
    LOG_TEST(5);

    LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(
        _DATA_URLS(VALID_OBJECT_ID,
                   "1.0","true",
                   FAKE_OBJECT_MEDIA_CAP_URL_503,
                   FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL));
    int num_refs_start = o->getNumRefs();
    {
        const int NUM_RETRIES = 5;
        LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD,NUM_RETRIES);

        // This should generate a retry
        mdc->fetchMedia(o);

        // Make sure no posts happened yet...
        ensure("post records before", gPostRecords->size(), 0);

        // Once, causes retry
        // Second, fires retry timer
        // Third, fires queue timer again
        for (int i=0; i<NUM_RETRIES; ++i)
        {
            ::pump_timers();  // Should pump (fire) the queue timer, causing a retry timer to be scheduled
            // XXX This ensure is not guaranteed, because scheduling a timer might actually get it pumped in the same loop
            //ensure("post records " + STR(i), gPostRecords->size(), i+1);
            ::pump_timers();  // Should pump (fire) the retry timer, scheduling the queue timer
        }

        // Do some extra pumps to make sure no other timer work occurs.
        ::pump_timers();
        ::pump_timers();
        ::pump_timers();

        // Make sure there were 2 posts
        ensure("post records after", gPostRecords->size(), NUM_RETRIES);
        for (int i=0; i<NUM_RETRIES; ++i)
        {
            ensure("[" + STR(i) + "] post url", (*gPostRecords)[i]["url"], FAKE_OBJECT_MEDIA_CAP_URL_503);
            ensure("[" + STR(i) + "] post GET", (*gPostRecords)[i]["body"]["verb"], "GET");
            ensure("[" + STR(i) + "] post object id", (*gPostRecords)[i]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID));
        }
        ensure("queue empty", mdc->isEmpty());
    }

    // Make sure everyone's destroyed properly
    ensure("REF COUNT", o->getNumRefs(), num_refs_start);
}
void mediadataclient_object_t::test<4>()
{
    //
    // Test queue ordering
    //
    LOG_TEST(4);

    LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(
        _DATA(VALID_OBJECT_ID_1,"1.0","true"));
    LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(
        _DATA(VALID_OBJECT_ID_2,"3.0","true"));
    LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(
        _DATA(VALID_OBJECT_ID_3,"2.0","true"));
    {
        LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
        const char *ORDERED_OBJECT_IDS[] = { VALID_OBJECT_ID_2, VALID_OBJECT_ID_3, VALID_OBJECT_ID_1 };
        mdc->fetchMedia(o1);
        mdc->fetchMedia(o2);
        mdc->fetchMedia(o3);

        // Make sure no posts happened yet...
        ensure("post records", gPostRecords->size(), 0);

        // tick 3 times...
        ::pump_timers();
        ensure("post records", gPostRecords->size(), 1);
        ::pump_timers();
        ensure("post records", gPostRecords->size(), 2);
        ::pump_timers();
        ensure("post records", gPostRecords->size(), 3);

        for( int i=0; i < 3; i++ )
        {
            ensure("[" + STR(i) + "] post url", (*gPostRecords)[i]["url"], FAKE_OBJECT_MEDIA_CAP_URL);
            ensure("[" + STR(i) + "] post GET", (*gPostRecords)[i]["body"]["verb"], "GET");
            ensure("[" + STR(i) + "] post object id", (*gPostRecords)[i]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(),
                   LLUUID(ORDERED_OBJECT_IDS[i]));
        }

        ensure("queue empty", mdc->isEmpty());
    }
    ensure("refcount of o1", o1->getNumRefs(), 1);
    ensure("refcount of o2", o2->getNumRefs(), 1);
    ensure("refcount of o3", o3->getNumRefs(), 1);
}
void mediadataclient_object_t::test<12>()
{
    //
    // Test the "not interesting enough" call
    //
    LOG_TEST(12);

    LLMediaDataClientObjectTest *object1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"1.0","true"));
    LLMediaDataClientObject::ptr_t o1 = object1;
    LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"2.0","true"));
    LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"3.0","true"));
    LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"4.0","true"));
    {
        LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);

        // queue up all 4 objects.  The first two are "interesting enough".
        // Firing the timer 4 times should therefore leave them.
        // Note that they should be sorted 4,3,2,1
        // Then, we'll make one "interesting enough", fire the timer a few
        // times, and make sure only it gets pulled off the queue
        gMinimumInterestLevel = 2.5;
        mdc->fetchMedia(o1);
        mdc->fetchMedia(o2);
        mdc->fetchMedia(o3);
        mdc->fetchMedia(o4);

        int tick_num = 0;

        // 0
        ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
        ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
        ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
        ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4));
        ensure(STR(tick_num) + ". post records", gPostRecords->size(), 0);

        ::pump_timers();
        ++tick_num;

        // 1 The first tick should remove object 4
        ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
        ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
        ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
        ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
        ensure(STR(tick_num) + ". post records", gPostRecords->size(), 1);
        ensure(STR(tick_num) + ". post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_4));

        ::pump_timers();
        ++tick_num;

        // 2 The second tick should send object 3
        ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
        ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
        ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
        ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
        ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2);
        ensure(STR(tick_num) + ". post object id", (*gPostRecords)[1]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_3));

        ::pump_timers();
        ++tick_num;

        // 3 The third tick should not pull off anything
        ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
        ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
        ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
        ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
        ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2);

        ::pump_timers();
        ++tick_num;

        // 4 The fourth tick (for good measure) should not pull off anything
        ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
        ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
        ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
        ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
        ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2);

        // Okay, now futz with object 1's interest, such that it is now
        // "interesting enough"
        object1->setMediaInterest((F64)5.0);

        // This should sort so that the queue is now [1 2]
        ::pump_timers();
        ++tick_num;

        // 5 The fifth tick should now identify objects 3 and 4 as no longer
        // needing "updating", and remove them from the queue
        ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1));
        ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
        ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
        ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
        ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3);
        ensure(STR(tick_num) + ". post object id", (*gPostRecords)[2]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_1));

        ::pump_timers();
        ++tick_num;

        // 6 The sixth tick should not pull off anything
        ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1));
        ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
        ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
        ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
        ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3);

        ::pump_timers();
        ++tick_num;

        // Whew....better NOT be empty ... o2 should still be there
        ensure("queue not empty", !mdc->isEmpty());

        // But, we need to clear the queue, or else we won't destroy MDC...
        // this is a strange interplay between the queue timer and the MDC
        mdc->removeFromQueue(o2);
        // tick
        ::pump_timers();
    }
    ensure("refcount of o1", o1->getNumRefs(), 1);
    ensure("refcount of o2", o2->getNumRefs(), 1);
    ensure("refcount of o3", o3->getNumRefs(), 1);
    ensure("refcount of o4", o4->getNumRefs(), 1);
}
void mediadataclient_object_t::test<10>()
{
    //
    // Test using the "round-robin" queue
    //
    LOG_TEST(10);

    LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"1.0","true"));
    LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"2.0","true"));
    LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"3.0","false"));
    LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"4.0","false"));
    {
        LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);

        // queue up all 4 objects.  The first two should be in the sorted
        // queue [2 1], the second in the round-robin queue.  The queues
        // are serviced interleaved, so we should expect:
        // 2, 3, 1, 4
        mdc->fetchMedia(o1);
        mdc->fetchMedia(o2);
        mdc->fetchMedia(o3);
        mdc->fetchMedia(o4);

        int tick_num = 0;

        // 0
        ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
        ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
        ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
        ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4));
        ensure(STR(tick_num) + ". post records", gPostRecords->size(), 0);

        ::pump_timers();
        ++tick_num;

        // 1 The first tick should remove object 2
        ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
        ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2));
        ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
        ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4));
        ensure(STR(tick_num) + ". post records", gPostRecords->size(), 1);
        ensure(STR(tick_num) + ". post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_2));

        ::pump_timers();
        ++tick_num;

        // 2 The second tick should send object 3
        ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
        ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2));
        ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
        ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4));
        ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2);
        ensure(STR(tick_num) + ". post object id", (*gPostRecords)[1]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_3));

        ::pump_timers();
        ++tick_num;

        // 3 The third tick should remove object 1
        ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1));
        ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2));
        ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
        ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4));
        ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3);
        ensure(STR(tick_num) + ". post object id", (*gPostRecords)[2]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_1));

        ::pump_timers();
        ++tick_num;

        // 4 The fourth tick should send object 4
        ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1));
        ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2));
        ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
        ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
        ensure(STR(tick_num) + ". post records", gPostRecords->size(), 4);
        ensure(STR(tick_num) + ". post object id", (*gPostRecords)[3]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_4));

        ::pump_timers();
        ++tick_num;

        // 5 The fifth tick should not change the state of anything.
        ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1));
        ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2));
        ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
        ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
        ensure(STR(tick_num) + ". post records", gPostRecords->size(), 4);

        ::pump_timers();

        // Whew....better be empty
        ensure("queue empty", mdc->isEmpty());
    }
    ensure("refcount of o1", o1->getNumRefs(), 1);
    ensure("refcount of o2", o2->getNumRefs(), 1);
    ensure("refcount of o3", o3->getNumRefs(), 1);
    ensure("refcount of o4", o4->getNumRefs(), 1);
}
void mediadataclient_object_t::test<9>()
{
    //
    // Test queue re-ordering
    //
    LOG_TEST(9);

    LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"40.0","true"));
    LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"30.0","true"));
    LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"20.0","true"));
    LLMediaDataClientObjectTest *object4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"10.0","true"));
    LLMediaDataClientObject::ptr_t o4 = object4;
    {
        LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);

        // queue up all 4 objects.  They should now be in the queue in
        // order 1 through 4, with 4 being at the front of the queue
        mdc->fetchMedia(o1);
        mdc->fetchMedia(o2);
        mdc->fetchMedia(o3);
        mdc->fetchMedia(o4);

        int tick_num = 0;

        ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
        ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
        ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
        ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4));
        ensure(STR(tick_num) + ". post records", gPostRecords->size(), 0);

        ::pump_timers();
        ++tick_num;

        // The first tick should remove the first one
        ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1));
        ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
        ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
        ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4));
        ensure(STR(tick_num) + ". post records", gPostRecords->size(), 1);

        // Now, pretend that object 4 moved relative to the avatar such
        // that it is now closest
        object4->setMediaInterest(50.0);

        ::pump_timers();
        ++tick_num;

        // The second tick should still pick off item 2, but then re-sort
        // have picked off object 4
        ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
        ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
        ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
        ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2);

        ::pump_timers();
        ++tick_num;

        // The third tick should pick off object 2
        ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2));
        ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
        ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3);

        // The fourth tick should pick off object 3
        ::pump_timers();
        ++tick_num;

        ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
        ensure(STR(tick_num) + ". post records", gPostRecords->size(), 4);

        ensure("queue empty", mdc->isEmpty());
    }
    ensure("refcount of o1", o1->getNumRefs(), 1);
    ensure("refcount of o2", o2->getNumRefs(), 1);
    ensure("refcount of o3", o3->getNumRefs(), 1);
    ensure("refcount of o4", o4->getNumRefs(), 1);
}