// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/wasm/wasm-objects-inl.h"
#include "src/wasm/wasm-opcodes.h"

#include "src/wasm/wasm-module-builder.h"
#include "test/cctest/cctest.h"
#include "test/cctest/manually-externalized-buffer.h"
#include "test/common/wasm/flag-utils.h"
#include "test/common/wasm/test-signatures.h"
#include "test/common/wasm/wasm-macro-gen.h"
#include "test/common/wasm/wasm-module-runner.h"

namespace v8 {
namespace internal {
namespace wasm {
namespace test_grow_memory {

using testing::CompileAndInstantiateForTesting;
using v8::internal::testing::ManuallyExternalizedBuffer;

namespace {
void ExportAsMain(WasmFunctionBuilder* f) {
  f->builder()->AddExport(CStrVector("main"), f);
}
#define EMIT_CODE_WITH_END(f, code)  \
  do {                               \
    f->EmitCode(code, sizeof(code)); \
    f->Emit(kExprEnd);               \
  } while (false)

void Cleanup(Isolate* isolate = CcTest::InitIsolateOnce()) {
  // By sending a low memory notifications, we will try hard to collect all
  // garbage and will therefore also invoke all weak callbacks of actually
  // unreachable persistent handles.
  reinterpret_cast<v8::Isolate*>(isolate)->LowMemoryNotification();
}
}  // namespace

TEST(GrowMemDetaches) {
  {
    Isolate* isolate = CcTest::InitIsolateOnce();
    HandleScope scope(isolate);
    Handle<WasmMemoryObject> memory_object =
        WasmMemoryObject::New(isolate, 16, 100, SharedFlag::kNotShared)
            .ToHandleChecked();
    Handle<JSArrayBuffer> buffer(memory_object->array_buffer(), isolate);
    int32_t result = WasmMemoryObject::Grow(isolate, memory_object, 0);
    CHECK_EQ(16, result);
    CHECK_NE(*buffer, memory_object->array_buffer());
    CHECK(buffer->was_detached());
  }
  Cleanup();
}

TEST(Externalized_GrowMemMemSize) {
  {
    Isolate* isolate = CcTest::InitIsolateOnce();
    HandleScope scope(isolate);
    Handle<WasmMemoryObject> memory_object =
        WasmMemoryObject::New(isolate, 16, 100, SharedFlag::kNotShared)
            .ToHandleChecked();
    ManuallyExternalizedBuffer external(
        handle(memory_object->array_buffer(), isolate));
    int32_t result = WasmMemoryObject::Grow(isolate, memory_object, 0);
    CHECK_EQ(16, result);
    CHECK_NE(*external.buffer_, memory_object->array_buffer());
    CHECK(external.buffer_->was_detached());
  }
  Cleanup();
}

TEST(Run_WasmModule_Buffer_Externalized_GrowMem) {
  {
    Isolate* isolate = CcTest::InitIsolateOnce();
    HandleScope scope(isolate);
    TestSignatures sigs;
    v8::internal::AccountingAllocator allocator;
    Zone zone(&allocator, ZONE_NAME);

    WasmModuleBuilder* builder = zone.New<WasmModuleBuilder>(&zone);
    WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v());
    ExportAsMain(f);
    byte code[] = {WASM_GROW_MEMORY(WASM_I32V_1(6)), WASM_DROP,
                   WASM_MEMORY_SIZE};
    EMIT_CODE_WITH_END(f, code);

    ZoneBuffer buffer(&zone);
    builder->WriteTo(&buffer);
    testing::SetupIsolateForWasmModule(isolate);
    ErrorThrower thrower(isolate, "Test");
    const Handle<WasmInstanceObject> instance =
        CompileAndInstantiateForTesting(
            isolate, &thrower, ModuleWireBytes(buffer.begin(), buffer.end()))
            .ToHandleChecked();
    Handle<WasmMemoryObject> memory_object(instance->memory_object(), isolate);

    // Fake the Embedder flow by externalizing the array buffer.
    ManuallyExternalizedBuffer external1(
        handle(memory_object->array_buffer(), isolate));

    // Grow using the API.
    uint32_t result = WasmMemoryObject::Grow(isolate, memory_object, 4);
    CHECK_EQ(16, result);
    CHECK(external1.buffer_->was_detached());  // growing always detaches
    CHECK_EQ(0, external1.buffer_->byte_length());

    CHECK_NE(*external1.buffer_, memory_object->array_buffer());

    // Fake the Embedder flow by externalizing the array buffer.
    ManuallyExternalizedBuffer external2(
        handle(memory_object->array_buffer(), isolate));

    // Grow using an internal Wasm bytecode.
    result = testing::CallWasmFunctionForTesting(isolate, instance, "main", 0,
                                                 nullptr);
    CHECK_EQ(26, result);
    CHECK(external2.buffer_->was_detached());  // growing always detaches
    CHECK_EQ(0, external2.buffer_->byte_length());
    CHECK_NE(*external2.buffer_, memory_object->array_buffer());
  }
  Cleanup();
}

}  // namespace test_grow_memory
}  // namespace wasm
}  // namespace internal
}  // namespace v8

#undef EMIT_CODE_WITH_END
