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

#include "include/core/SkTypes.h"
#include "include/private/chromium/SkChromeRemoteGlyphCache.h"
#include "src/core/SkDescriptor.h"
#include "src/core/SkFontPriv.h"
#include "src/core/SkReadBuffer.h"
#include "src/core/SkScalerContext.h"
#include "src/core/SkWriteBuffer.h"
#include "src/gpu/ganesh/GrResourceProvider.h"
#include "tests/Test.h"

#include <memory>

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());
    }
}
