// 
// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use. 
// 


#include "config.h"

#include "../src/interface.h"
#include "../src/util.h"
#include "util.h"
#include <iostream>
#include <vector>
#include <cstdlib>
#include <cstdio>

void TestDamagedBitStream1()
{
    std::vector<BYTE> rgbyteCompressed; 
    if (!ReadFile("test/incorrect_images/InfiniteLoopFFMPEG.jls", &rgbyteCompressed, 0))
        return;

    std::vector<BYTE> rgbyteOut(256 * 256 * 2); 
    JLS_ERROR error = JpegLsDecode(&rgbyteOut[0], rgbyteOut.size(), &rgbyteCompressed[0], int(rgbyteCompressed.size()), NULL);
    ASSERT(error == InvalidCompressedData);
}


void TestDamagedBitStream2()
{
    std::vector<BYTE> rgbyteCompressed; 
    if (!ReadFile("test/lena8b.jls", &rgbyteCompressed, 0))
        return;

    rgbyteCompressed.resize(900);
    rgbyteCompressed.resize(40000,3);

    std::vector<BYTE> rgbyteOut(512 * 512); 
    JLS_ERROR error = JpegLsDecode(&rgbyteOut[0], rgbyteOut.size(), &rgbyteCompressed[0], int(rgbyteCompressed.size()), NULL);
    ASSERT(error == InvalidCompressedData);
}



void TestDamagedBitStream3()
{
    std::vector<BYTE> rgbyteCompressed; 
    if (!ReadFile("test/lena8b.jls", &rgbyteCompressed, 0))
        return; 

    rgbyteCompressed[300] = 0xFF;
    rgbyteCompressed[301] = 0xFF;

    std::vector<BYTE> rgbyteOut(512 * 512); 
    JLS_ERROR error = JpegLsDecode(&rgbyteOut[0], rgbyteOut.size(), &rgbyteCompressed[0], int(rgbyteCompressed.size()), NULL);
    ASSERT(error == InvalidCompressedData);
}


void TestFileWithRandomHeaderDamage(SZC filename)
{
    std::vector<BYTE> rgbyteCompressedOrg;  
    if (!ReadFile(filename, &rgbyteCompressedOrg, 0))
        return; 

    srand(102347325);

    std::vector<BYTE> rgbyteOut(512 * 512); 

    for (int i = 0; i < 40; ++i)
    {
        std::vector<BYTE> rgbyteCompressedTest(rgbyteCompressedOrg);
        std::vector<int> errors(10,0);

        for (int j = 0; j < 20; ++j)
        {
            rgbyteCompressedTest[i] = (BYTE)rand();
            rgbyteCompressedTest[i+1] = (BYTE)rand();               
            rgbyteCompressedTest[i+2] = (BYTE)rand();       
            rgbyteCompressedTest[i+3] = (BYTE)rand();       
            
            JLS_ERROR error = JpegLsDecode(&rgbyteOut[0], rgbyteOut.size(), &rgbyteCompressedTest[0], int(rgbyteCompressedTest.size()), NULL);
            errors[error] = errors[error] + 1;
        }

        std::cout << "With garbage input at index " << i << ": ";
        for(unsigned int error = 0; error < errors.size(); ++error)
        {
            if (errors[error] == 0)
                continue;

            std::cout <<  errors[error] << "x error (" << error << "); ";
        }

        std::cout << "\r\n";
    }
}


void TestRandomMalformedHeader()
{
    TestFileWithRandomHeaderDamage("test/conformance/T8C0E0.JLS");
    TestFileWithRandomHeaderDamage("test/conformance/T8C1E0.JLS");
    TestFileWithRandomHeaderDamage("test/conformance/T8C2E0.JLS");
}


void DamagedBitstreamTests()
{
    printf("Test Damaged bitstream\r\n");
    TestDamagedBitStream1();
    TestDamagedBitStream2();
    TestDamagedBitStream3();

    printf("Begin random malformed bitstream tests: \r\n");
    TestRandomMalformedHeader();
    printf("End randommalformed bitstream tests: \r\n");
}
