A C++ class to handle one decompressor plugin instance. 
#define TEST_RUNTIME 600 // seconds
#include <test.h>
#include <lunchbox/buffer.h>
#include <lunchbox/clock.h>
#include <lunchbox/compressor.h>
#include <lunchbox/compressorInfo.h>
#include <lunchbox/compressorResult.h>
#include <lunchbox/decompressor.h>
#include <lunchbox/file.h>
#include <lunchbox/memoryMap.h>
#include <lunchbox/plugin.h>
#include <lunchbox/pluginRegistry.h>
#include <lunchbox/rng.h>
#include <algorithm>
using namespace lunchbox;
void _testFile();
void _testRandom();
void _testData( const uint32_t nameCompressor, const std::string& name,
                const uint8_t* data, const uint64_t size );
std::vector< uint32_t > getCompressorNames( const uint32_t tokenType );
                  const std::string& ext );
uint64_t _result = 0;
uint64_t _size = 0;
float _compressionTime = 0;
float _decompressionTime = 0;
float _baseTime = 0.f;
int main( int, char** )
{
    registry.
addDirectory( std::string( LUNCHBOX_BUILD_DIR ) + 
"/lib" );
 
    TEST( registry.addLunchboxPlugins( ));
    registry.init();
    _testFile();
    _testRandom();
    registry.exit();
    TEST( !compressor );
    TEST( !decompressor.
isGood( ));
 
    TEST( !decompressor );
    return EXIT_SUCCESS;
}
std::vector< uint32_t > getCompressorNames( const uint32_t tokenType )
{
    const Plugins& plugins = registry.getPlugins();
    std::vector< uint32_t > names;
    for( PluginsCIter i = plugins.begin(); i != plugins.end(); ++i )
    {
        const CompressorInfos& infos = (*i)->getInfos();
        for( CompressorInfosCIter j = infos.begin(); j != infos.end(); ++j )
        {
            if ( (*j).tokenType == tokenType )
                names.push_back( (*j).name );
        }
    }
    std::sort( names.begin(), names.end( ));
    return names;
}
void _testData( const uint32_t compressorName, const std::string& name,
                const uint8_t* data, const uint64_t size )
{
    Compressor compressor( registry, compressorName );
 
    TEST( compressor );
    TESTINFO( decompressor.
isGood(), compressorName );
 
    TESTINFO( decompressor, compressorName );
    uint64_t inDims[2]  = { 0, size };
    compressor.
compress( const_cast<uint8_t*>(data), inDims, flags );
 
    compressor.
compress( const_cast<uint8_t*>(data), inDims, flags );
 
    const float compressTime = clock.
getTimef();
 
    const uint64_t compressedSize = compressed.
getSize();
 
    std::vector< void * > chunks;
    std::vector< uint64_t > chunkSizes;
    chunks.resize( compressed.chunks.size( ));
    chunkSizes.resize( chunks.size( ));
    for( unsigned i = 0; i < chunks.size(); ++i )
    {
        chunks[ i ] = compressed.chunks[i].data;
        chunkSizes[ i ] =  compressed.chunks[i].getNumBytes();
    }
    uint8_t* outData = result.
getData();
 
    decompressor.
decompress( &chunks.front(), &chunkSizes.front(),
 
                             unsigned( chunks.size( )), outData, inDims );
    decompressor.
decompress( &chunks.front(), &chunkSizes.front(),
 
                             unsigned(chunks.size()), outData, inDims);
    const float decompressTime = clock.
getTimef();
 
    TEST( memcmp( outData, data, size ) == 0 );
    std::cout  << std::setw(20) << name << ", 0x" << std::setw(8)
               << std::setfill( '0' ) << std::hex << compressorName << std::dec
               << std::setfill(' ') << ", " << std::setw(10) << size << ", "
               << std::setw(10) << compressedSize << ", " << std::setw(10)
               << compressTime << ", " << std::setw(10) << decompressTime
               << std::endl;
    _size += size;
    _result += compressedSize;
    _compressionTime += compressTime;
    _decompressionTime += decompressTime;
}
void _testFile()
{
    std::vector< uint32_t >compressorNames =
    std::vector< std::string > files;
    getFiles( "", files, ".*\\.dll" );
    getFiles( "", files, ".*\\.exe" );
    getFiles( "", files, ".*\\.so" );
    getFiles( "../bin", files, ".*\\.dll" );
    getFiles( "../lib", files, ".*\\.so" );
    getFiles( "../../install/bin", files, ".*\\.dll" );
    getFiles( "../../install/lib", files, ".*\\.so" );
    getFiles( "images", files, ".*\\.rgb" );
    getFiles( "", files, ".*\\.a" );
    getFiles( "", files, ".*\\.dylib" );
    getFiles( "/Users/eile/Library/Models/mediumPly/", files, ".*\\.bin" );
    getFiles( "/Users/eile/Library/Models/mediumPly/", files, ".*\\.ply" );
    getFiles( "/home/eilemann/Software/Models/mediumPly/", files, ".*\\.bin" );
    getFiles( "/home/eilemann/Software/Models/mediumPly/", files, ".*\\.ply" );
    
    const size_t maxFiles = 30;
    if( files.size() > maxFiles )
    {
        const size_t cut = files.size() - maxFiles;
        for( size_t i = 0; i < cut; ++i )
            files.erase( files.begin() + (i * 997 ) % files.size( ));
    }
    std::cout.setf( std::ios::right, std::ios::adjustfield );
    std::cout.precision( 5 );
    std::cout << "                File, Compressor, Uncompress, "
              << "Compressed,     t_comp,   t_decomp" << std::endl;
    for( std::vector< uint32_t >::const_iterator i = compressorNames.begin();
         i != compressorNames.end(); ++i )
    {
        _result = 0;
        _size = 0;
        _compressionTime = 0;
        _decompressionTime = 0;
        for( StringsCIter j = files.begin(); j != files.end(); ++j )
        {
            const uint8_t* data = 
static_cast<const uint8_t*
>( file.
map( *j ));
 
            if( !data )
            {
                LBERROR << 
"Can't mmap " << *j << std::endl;
 
                continue;
            }
            const size_t size = file.
getSize();
 
            _testData( *i, name, data, size );
        }
        if( _baseTime == 0.f )
            _baseTime = _compressionTime + _decompressionTime;
        std::cout << std::setw(24) << "Total, 0x" << std::setw(8)
                  << std::setfill( '0' ) << std::hex << *i << std::dec
                  << std::setfill(' ') << ", " << std::setw(10) << _size << ", "
                  << std::setw(10) << _result << ", " << std::setw(10)
                  << _compressionTime << ", " << std::setw(10)
                  << _decompressionTime << std::endl
                  << "    info->ratio = " << float(_result) / float(_size)
                  << "f;" << std::endl
                  << "    info->speed = " << float(_baseTime) /
                                    float(_compressionTime + _decompressionTime)
                  << "f;" << std::endl << std::endl;
    }
}
void _testRandom()
{
    ssize_t size = LB_10MB;
    uint8_t* data = new uint8_t[size];
#pragma omp parallel for
    for( ssize_t i = 0; i < size; ++i )
        data[i] = rng.
get< uint8_t >();
 
    std::vector< uint32_t >compressorNames =
    _result = 0;
    _size = 0;
    _compressionTime = 0;
    _decompressionTime = 0;
    for( std::vector<uint32_t>::const_iterator i = compressorNames.begin();
         i != compressorNames.end(); ++i )
    {
        size = LB_10MB;
        for( size_t j = 0; j<8; ++j ) 
        {
            _testData( *i, "Random data", data, size );
            --size;
        }
        std::cout << std::setw(24) << "Total, 0x" << std::setw(8)
                  << std::setfill( '0' ) << std::hex << *i << std::dec
                  << std::setfill(' ') << ", " << std::setw(10) << _size << ", "
                  << std::setw(10) << _result << ", " << std::setw(10)
                  << _compressionTime << ", " << std::setw(10)
                  << _decompressionTime << std::endl << std::endl;
   }
    delete [] data;
}
                  const std::string& ext )
{
    Strings paths = registry.getDirectories();
 
    if( !path.empty( ))
        paths.push_back( path );
    for( uint64_t j = 0; j < paths.size(); ++j )
    {
        for( StringsCIter i = candidates.begin(); i != candidates.end(); ++i )
        {
            const std::string& filename = *i;
            files.push_back( paths[j] + '/' + filename );
        }
    }
    return files;
}