void testModeMetaDataAndBinaryData()
{
    // initialize list
    MSData msd;
    shared_ptr<SpectrumListSimple> sl(new SpectrumListSimple);
    sl->spectra.push_back(makeSpectrumPtr(0, "S1"));
    sl->spectra.push_back(makeSpectrumPtr(1, "S2"));
    sl->spectra.push_back(makeSpectrumPtr(2, "S3"));
    sl->spectra.push_back(makeSpectrumPtr(3, "S4"));
    msd.run.spectrumListPtr = sl;

    // SpectrumListSimple returns the same shared_ptrs regardless of caching;
    // serializing to MGF and back will produce different shared_ptrs
    boost::shared_ptr<stringstream> ss(new stringstream);
    Serializer_MGF serializer;
    serializer.write(*ss, msd, 0);
    serializer.read(ss, msd);

    // access a series of spectra and make sure the cache behaves appropriately:
    // in metadata-and-binary-data mode, entries in the cache should:
    // - always have metadata
    // - always have binary data

    SpectrumPtr s;

    SpectrumListCache slc(msd.run.spectrumListPtr, MemoryMRUCacheMode_MetaDataAndBinaryData, 2);
    SpectrumListCache::CacheType& cache = slc.spectrumCache();

    unit_assert(cache.empty());
    unit_assert_operator_equal(2, cache.max_size());

    // metadata-only access should not affect the cache
    s = slc.spectrum(0, false);

    if (os_) *os_ << cache << endl;
    unit_assert(cache.empty());
    unit_assert_operator_equal(0, cache.size());

    s = slc.spectrum(1, true);

    // pointers should be equal
    unit_assert_operator_equal(slc.spectrum(1, true), s);

    if (os_) *os_ << cache << endl;
    unit_assert_operator_equal(1, cache.size());
    unit_assert_operator_equal(1, cache.mru().spectrum->index);
    unit_assert(spectrumHasMetadata(*cache.mru().spectrum));
    unit_assert(spectrumHasBinaryData(*cache.mru().spectrum));

    s = slc.spectrum(2, false);

    if (os_) *os_ << cache << endl;
    unit_assert_operator_equal(1, cache.size());
    unit_assert_operator_equal(1, cache.mru().spectrum->index);
    unit_assert(spectrumHasMetadata(*cache.mru().spectrum));
    unit_assert(spectrumHasBinaryData(*cache.mru().spectrum));

    s = slc.spectrum(3, true);

    // pointers should be equal
    unit_assert_operator_equal(slc.spectrum(3, true), s);

    if (os_) *os_ << cache << endl;
    unit_assert_operator_equal(2, cache.size());
    unit_assert_operator_equal(3, cache.mru().spectrum->index);
    unit_assert(spectrumHasMetadata(*cache.mru().spectrum));
    unit_assert(spectrumHasBinaryData(*cache.mru().spectrum));
    unit_assert_operator_equal(1, cache.lru().spectrum->index);
    unit_assert(spectrumHasMetadata(*cache.lru().spectrum));
    unit_assert(spectrumHasBinaryData(*cache.lru().spectrum));

    s = slc.spectrum(2, true);

    if (os_) *os_ << cache << endl;
    unit_assert_operator_equal(2, cache.size());
    unit_assert_operator_equal(2, cache.mru().spectrum->index);
    unit_assert(spectrumHasMetadata(*cache.mru().spectrum));
    unit_assert(spectrumHasBinaryData(*cache.mru().spectrum));
    unit_assert_operator_equal(3, cache.lru().spectrum->index);
    unit_assert(spectrumHasMetadata(*cache.lru().spectrum));
    unit_assert(spectrumHasBinaryData(*cache.lru().spectrum));
}