/*
 * Copyright 2019 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/core/SkData.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkTypes.h"
#include "src/core/SkChecksum.h"
#include "src/core/SkDescriptor.h"
#include "src/core/SkReadBuffer.h"
#include "src/core/SkScalerContext.h"
#include "src/core/SkWriteBuffer.h"
#include "tests/Test.h"

#include <cstddef>
#include <cstdint>
#include <memory>
#include <optional>

class SkDescriptorTestHelper {
public:
    static void SetLength(SkDescriptor* desc, size_t length) { desc->fLength = length; }
    static void SetCount(SkDescriptor* desc, uint32_t count) { desc->fCount = count; }
};

DEF_TEST(Descriptor_empty, r) {
    const size_t size = sizeof(SkDescriptor);

    auto desc = SkDescriptor::Alloc(size);
    REPORTER_ASSERT(r, desc->isValid());
    REPORTER_ASSERT(r, desc->getLength() == size);
}

DEF_TEST(Descriptor_valid_simple, r) {
    const size_t size =
            sizeof(SkDescriptor) + sizeof(SkDescriptor::Entry) + sizeof(SkScalerContextRec);

    auto desc = SkDescriptor::Alloc(size);
    SkScalerContextRec rec;
    desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
    REPORTER_ASSERT(r, desc->isValid());
    REPORTER_ASSERT(r, desc->getLength() == size);

    SkDescriptorTestHelper::SetLength(desc.get(), size - 4);
    REPORTER_ASSERT(r, !desc->isValid());
}

DEF_TEST(Descriptor_valid_simple_extra_space, r) {
    const size_t extra_space = 100;
    const size_t size =
            sizeof(SkDescriptor) + sizeof(SkDescriptor::Entry) + sizeof(SkScalerContextRec);

    auto desc = SkDescriptor::Alloc(size + extra_space);
    SkScalerContextRec rec;
    desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
    REPORTER_ASSERT(r, desc->isValid());
    REPORTER_ASSERT(r, desc->getLength() == size);

    SkDescriptorTestHelper::SetLength(desc.get(), size - 4);
    REPORTER_ASSERT(r, !desc->isValid());
}

DEF_TEST(Descriptor_valid_more_tags, r) {
    const size_t effectSize = 16;
    const size_t testSize = 32;
    const size_t size = sizeof(SkDescriptor) + 3 * sizeof(SkDescriptor::Entry) +
                        sizeof(SkScalerContextRec) + effectSize + testSize;

    auto desc = SkDescriptor::Alloc(size);
    SkScalerContextRec rec;
    desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
    desc->addEntry(kEffects_SkDescriptorTag, effectSize, nullptr);
    desc->addEntry(SkSetFourByteTag('t', 'e', 's', 't'), testSize, nullptr);
    REPORTER_ASSERT(r, desc->isValid());
    REPORTER_ASSERT(r, desc->getLength() == size);

    SkDescriptorTestHelper::SetLength(desc.get(), size - 4);
    REPORTER_ASSERT(r, !desc->isValid());
}

DEF_TEST(Descriptor_invalid_rec_size, r) {
    const size_t size =
            sizeof(SkDescriptor) + sizeof(SkDescriptor::Entry) + sizeof(SkScalerContextRec) - 4;

    auto desc = SkDescriptor::Alloc(size);
    SkScalerContextRec rec;
    desc->addEntry(kRec_SkDescriptorTag, sizeof(rec) - 4, &rec);
    REPORTER_ASSERT(r, desc->getLength() == size);
    REPORTER_ASSERT(r, !desc->isValid());
}

DEF_TEST(Descriptor_invalid_length, r) {
    const size_t size = sizeof(SkDescriptor) + sizeof(SkDescriptor::Entry);
    const size_t effect_size = 1000;

    auto desc = SkDescriptor::Alloc(size);
    desc->addEntry(kEffects_SkDescriptorTag, effect_size, nullptr);

    SkDescriptorTestHelper::SetLength(desc.get(), size);
    REPORTER_ASSERT(r, !desc->isValid());

    SkDescriptorTestHelper::SetLength(desc.get(), size + effect_size);
    REPORTER_ASSERT(r, desc->isValid());
}

DEF_TEST(Descriptor_entry_too_big, r) {
    const size_t size = sizeof(SkDescriptor) + sizeof(SkDescriptor::Entry) + 4;
    // Must be less than fLength, but big enough to be bigger then fLength when added.
    const size_t effect_size = sizeof(SkDescriptor) + sizeof(SkDescriptor::Entry);

    auto desc = SkDescriptor::Alloc(size);

    desc->addEntry(kEffects_SkDescriptorTag, effect_size, nullptr);

    SkDescriptorTestHelper::SetLength(desc.get(), size);
    SkDescriptorTestHelper::SetCount(desc.get(), 2);
    REPORTER_ASSERT(r, !desc->isValid());

    SkDescriptorTestHelper::SetLength(desc.get(), size);
    SkDescriptorTestHelper::SetCount(desc.get(), 1);
    REPORTER_ASSERT(r, !desc->isValid());
}

DEF_TEST(Descriptor_entry_over_end, r) {
    auto desc = SkDescriptor::Alloc(36);

    // Make the start of the Entry be in the SkDescriptor, but the second half falls out side the
    // SkDescriptor. So: 12 (for descriptor) + 8 (for entry) + 12 (for entry length) = 32. An
    // An Entry is 8 bytes, so 4 bytes are < 36 and 4 bytes > 36.
    desc->addEntry(kEffects_SkDescriptorTag, 12, nullptr);

    SkDescriptorTestHelper::SetLength(desc.get(), 36);
    SkDescriptorTestHelper::SetCount(desc.get(), 2);
    REPORTER_ASSERT(r, !desc->isValid());
}

DEF_TEST(Descriptor_flatten_unflatten, r) {
    {
        SkBinaryWriteBuffer writer({});
        auto desc = SkDescriptor::Alloc(sizeof(SkDescriptor));
        desc->computeChecksum();
        desc->flatten(writer);
        auto data = writer.snapshotAsData();
        SkReadBuffer reader{data->data(), data->size()};
        auto ad = SkAutoDescriptor::MakeFromBuffer(reader);
        REPORTER_ASSERT(r, ad.has_value());
        REPORTER_ASSERT(r, ad->getDesc()->isValid());
    }

    {  // broken header
        SkBinaryWriteBuffer writer({});
        writer.writeInt(0);  // fChecksum
        auto data = writer.snapshotAsData();
        SkReadBuffer reader{data->data(), data->size()};
        auto ad = SkAutoDescriptor::MakeFromBuffer(reader);
        REPORTER_ASSERT(r, !ad.has_value());
    }

    {  // length too big
        SkBinaryWriteBuffer writer({});
        // Simulate a broken header
        writer.writeInt(0);    // fChecksum
        writer.writeInt(4000); // fLength
        writer.writeInt(0);    // fCount
        auto data = writer.snapshotAsData();
        SkReadBuffer reader{data->data(), data->size()};
        auto ad = SkAutoDescriptor::MakeFromBuffer(reader);
        REPORTER_ASSERT(r, !ad.has_value());
    }

    {  // length too small
        SkBinaryWriteBuffer writer({});
        // Simulate a broken header
        writer.writeInt(0);    // fChecksum
        writer.writeInt(3);    // fLength
        writer.writeInt(0);    // fCount
        auto data = writer.snapshotAsData();
        SkReadBuffer reader{data->data(), data->size()};
        auto ad = SkAutoDescriptor::MakeFromBuffer(reader);
        REPORTER_ASSERT(r, !ad.has_value());
    }

    {  // garbage in count
        SkBinaryWriteBuffer writer({});
        // Simulate a broken header
        writer.writeInt(0);    // fChecksum
        writer.writeInt(20);   // fLength
        writer.writeInt(10);   // fCount
        writer.writeInt(0);
        writer.writeInt(0);
        auto data = writer.snapshotAsData();
        SkReadBuffer reader{data->data(), data->size()};
        auto ad = SkAutoDescriptor::MakeFromBuffer(reader);
        REPORTER_ASSERT(r, !ad.has_value());
    }

    {  // unaligned length
        // SkDescriptor + entry tag + entry len + entry data(3 bytes only)
        static constexpr uint32_t datalen = sizeof(SkDescriptor) + 11;
        uint32_t data32[] = {
            // SkDescriptor
            0,       // checksum
            datalen, // desc.fLength
            1,       // desc.fCount

            // payload
            1,       // entry tag
            3,       // entry len
            0,       // entry data
        };
        data32[0] = SkChecksum::Hash32(data32 + 1, datalen - 4);

        SkReadBuffer reader{data32, sizeof(data32)};
        auto ad = SkAutoDescriptor::MakeFromBuffer(reader);
        REPORTER_ASSERT(r, !ad.has_value());
    }

}
