Index: test/cctest/wasm/test-run-wasm-module.cc |
diff --git a/test/cctest/wasm/test-run-wasm-module.cc b/test/cctest/wasm/test-run-wasm-module.cc |
index 3cc37048f895663dbab2f1d61367a235ad866cde..4f4f496d6b21956558908e981293fc21f9a8927e 100644 |
--- a/test/cctest/wasm/test-run-wasm-module.cc |
+++ b/test/cctest/wasm/test-run-wasm-module.cc |
@@ -173,105 +173,192 @@ TEST(Run_WasmModule_Global) { |
TestModule(&zone, builder, 97); |
} |
-TEST(Run_WasmModule_Serialization) { |
- static const char* kFunctionName = "increment"; |
- v8::internal::AccountingAllocator allocator; |
- Zone zone(&allocator, ZONE_NAME); |
+// Approximate gtest TEST_F style, in case we adopt gtest. |
+class WasmSerializationTest { |
+ public: |
+ WasmSerializationTest() : zone_(&allocator_, ZONE_NAME) { |
+ // Don't call here if we move to gtest. |
+ SetUp(); |
+ } |
- WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone); |
- TestSignatures sigs; |
+ void ClearSerializedData() { |
+ serialized_bytes_.first = nullptr; |
+ serialized_bytes_.second = 0; |
+ } |
- WasmFunctionBuilder* f = builder->AddFunction(sigs.i_i()); |
- byte code[] = {WASM_GET_LOCAL(0), kExprI32Const, 1, kExprI32Add}; |
- f->EmitCode(code, sizeof(code)); |
- f->ExportAs(CStrVector(kFunctionName)); |
+ void InvalidateVersion() { |
+ uint32_t* buffer = reinterpret_cast<uint32_t*>( |
+ const_cast<uint8_t*>(serialized_bytes_.first)); |
+ buffer[SerializedCodeData::kVersionHashOffset] = Version::Hash() + 1; |
+ } |
- ZoneBuffer buffer(&zone); |
- builder->WriteTo(buffer); |
+ void InvalidateWireBytes() { |
+ memset(const_cast<uint8_t*>(wire_bytes_.first), '\0', |
+ wire_bytes_.second / 2); |
+ } |
- Isolate* isolate = CcTest::InitIsolateOnce(); |
- ErrorThrower thrower(isolate, ""); |
- uint8_t* bytes = nullptr; |
- size_t bytes_size = 0; |
- v8::WasmCompiledModule::SerializedModule data; |
- { |
- HandleScope scope(isolate); |
- testing::SetupIsolateForWasmModule(isolate); |
- |
- ModuleResult decoding_result = DecodeWasmModule( |
- isolate, &zone, buffer.begin(), buffer.end(), false, kWasmOrigin); |
- std::unique_ptr<const WasmModule> module(decoding_result.val); |
- CHECK(!decoding_result.failed()); |
- |
- MaybeHandle<WasmCompiledModule> compiled_module = |
- module->CompileFunctions(isolate, &thrower); |
- CHECK(!compiled_module.is_null()); |
- Handle<JSObject> module_obj = CreateCompiledModuleObject( |
- isolate, compiled_module.ToHandleChecked(), ModuleOrigin::kWasmOrigin); |
- v8::Local<v8::Object> v8_module_obj = v8::Utils::ToLocal(module_obj); |
- CHECK(v8_module_obj->IsWebAssemblyCompiledModule()); |
- |
- v8::Local<v8::WasmCompiledModule> v8_compiled_module = |
- v8_module_obj.As<v8::WasmCompiledModule>(); |
- v8::Local<v8::String> uncompiled_bytes = |
- v8_compiled_module->GetWasmWireBytes(); |
- bytes_size = static_cast<size_t>(uncompiled_bytes->Length()); |
- bytes = zone.NewArray<uint8_t>(uncompiled_bytes->Length()); |
- uncompiled_bytes->WriteOneByte(bytes); |
- data = v8_compiled_module->Serialize(); |
+ v8::MaybeLocal<v8::WasmCompiledModule> Deserialize() { |
+ ErrorThrower thrower(current_isolate(), ""); |
+ v8::MaybeLocal<v8::WasmCompiledModule> deserialized = |
+ v8::WasmCompiledModule::DeserializeOrCompile( |
+ current_isolate_v8(), serialized_bytes(), wire_bytes()); |
+ return deserialized; |
} |
- v8::WasmCompiledModule::CallerOwnedBuffer wire_bytes = { |
- const_cast<const uint8_t*>(bytes), bytes_size}; |
- |
- v8::WasmCompiledModule::CallerOwnedBuffer serialized_bytes = { |
- data.first.get(), data.second}; |
- v8::Isolate::CreateParams create_params; |
- create_params.array_buffer_allocator = |
- CcTest::InitIsolateOnce()->array_buffer_allocator(); |
- |
- for (int i = 0; i < 3; ++i) { |
- v8::Isolate* v8_isolate = v8::Isolate::New(create_params); |
- if (i == 1) { |
- // Invalidate the header by providing a mismatched version |
- uint32_t* buffer = reinterpret_cast<uint32_t*>( |
- const_cast<uint8_t*>(serialized_bytes.first)); |
- buffer[SerializedCodeData::kVersionHashOffset] = Version::Hash() + 1; |
+ void DeserializeAndRun() { |
+ ErrorThrower thrower(current_isolate(), ""); |
+ v8::Local<v8::WasmCompiledModule> deserialized_module; |
+ CHECK(Deserialize().ToLocal(&deserialized_module)); |
+ Handle<JSObject> module_object = |
+ Handle<JSObject>::cast(v8::Utils::OpenHandle(*deserialized_module)); |
+ { |
+ DisallowHeapAllocation assume_no_gc; |
+ Handle<WasmCompiledModule> compiled_part( |
+ WasmCompiledModule::cast(module_object->GetInternalField(0)), |
+ current_isolate()); |
+ CHECK_EQ(memcmp(compiled_part->module_bytes()->GetCharsAddress(), |
+ wire_bytes().first, wire_bytes().second), |
+ 0); |
} |
+ Handle<JSObject> instance = |
+ WasmModule::Instantiate(current_isolate(), &thrower, module_object, |
+ Handle<JSReceiver>::null(), |
+ Handle<JSArrayBuffer>::null()) |
+ .ToHandleChecked(); |
+ Handle<Object> params[1] = { |
+ Handle<Object>(Smi::FromInt(41), current_isolate())}; |
+ int32_t result = testing::CallWasmFunctionForTesting( |
+ current_isolate(), instance, &thrower, kFunctionName, 1, params, |
+ ModuleOrigin::kWasmOrigin); |
+ CHECK(result == 42); |
+ } |
- if (i == 2) { |
- // Provide no serialized data to force recompilation. |
- serialized_bytes.first = nullptr; |
- serialized_bytes.second = 0; |
- } |
+ Isolate* current_isolate() { |
+ return reinterpret_cast<Isolate*>(current_isolate_v8_); |
+ } |
+ |
+ ~WasmSerializationTest() { |
+ // Don't call from here if we move to gtest |
+ TearDown(); |
+ } |
+ |
+ private: |
+ static const char* kFunctionName; |
+ |
+ Zone* zone() { return &zone_; } |
+ const v8::WasmCompiledModule::CallerOwnedBuffer& wire_bytes() const { |
+ return wire_bytes_; |
+ } |
+ |
+ const v8::WasmCompiledModule::CallerOwnedBuffer& serialized_bytes() const { |
+ return serialized_bytes_; |
+ } |
+ |
+ v8::Isolate* current_isolate_v8() { return current_isolate_v8_; } |
+ |
+ void SetUp() { |
+ WasmModuleBuilder* builder = new (zone()) WasmModuleBuilder(zone()); |
+ TestSignatures sigs; |
+ |
+ WasmFunctionBuilder* f = builder->AddFunction(sigs.i_i()); |
+ byte code[] = {WASM_GET_LOCAL(0), kExprI32Const, 1, kExprI32Add}; |
+ f->EmitCode(code, sizeof(code)); |
+ f->ExportAs(CStrVector(kFunctionName)); |
+ |
+ ZoneBuffer buffer(&zone_); |
+ builder->WriteTo(buffer); |
+ |
+ Isolate* serialization_isolate = CcTest::InitIsolateOnce(); |
+ ErrorThrower thrower(serialization_isolate, ""); |
+ uint8_t* bytes = nullptr; |
+ size_t bytes_size = 0; |
{ |
- v8::Isolate::Scope isolate_scope(v8_isolate); |
- v8::HandleScope new_scope(v8_isolate); |
- v8::Local<v8::Context> new_ctx = v8::Context::New(v8_isolate); |
- new_ctx->Enter(); |
- isolate = reinterpret_cast<Isolate*>(v8_isolate); |
- testing::SetupIsolateForWasmModule(isolate); |
- v8::MaybeLocal<v8::WasmCompiledModule> deserialized = |
- v8::WasmCompiledModule::DeserializeOrCompile( |
- v8_isolate, serialized_bytes, wire_bytes); |
- v8::Local<v8::WasmCompiledModule> compiled_module; |
- CHECK(deserialized.ToLocal(&compiled_module)); |
- Handle<JSObject> module_object = |
- Handle<JSObject>::cast(v8::Utils::OpenHandle(*compiled_module)); |
- Handle<JSObject> instance = |
- WasmModule::Instantiate(isolate, &thrower, module_object, |
- Handle<JSReceiver>::null(), |
- Handle<JSArrayBuffer>::null()) |
- .ToHandleChecked(); |
- Handle<Object> params[1] = {Handle<Object>(Smi::FromInt(41), isolate)}; |
- int32_t result = testing::CallWasmFunctionForTesting( |
- isolate, instance, &thrower, kFunctionName, 1, params, |
+ HandleScope scope(serialization_isolate); |
+ testing::SetupIsolateForWasmModule(serialization_isolate); |
+ |
+ ModuleResult decoding_result = |
+ DecodeWasmModule(serialization_isolate, zone(), buffer.begin(), |
+ buffer.end(), false, kWasmOrigin); |
+ std::unique_ptr<const WasmModule> module(decoding_result.val); |
+ CHECK(!decoding_result.failed()); |
+ |
+ MaybeHandle<WasmCompiledModule> compiled_module = |
+ module->CompileFunctions(serialization_isolate, &thrower); |
+ CHECK(!compiled_module.is_null()); |
+ Handle<JSObject> module_obj = CreateCompiledModuleObject( |
+ serialization_isolate, compiled_module.ToHandleChecked(), |
ModuleOrigin::kWasmOrigin); |
- CHECK(result == 42); |
- new_ctx->Exit(); |
+ v8::Local<v8::Object> v8_module_obj = v8::Utils::ToLocal(module_obj); |
+ CHECK(v8_module_obj->IsWebAssemblyCompiledModule()); |
+ |
+ v8::Local<v8::WasmCompiledModule> v8_compiled_module = |
+ v8_module_obj.As<v8::WasmCompiledModule>(); |
+ v8::Local<v8::String> uncompiled_bytes = |
+ v8_compiled_module->GetWasmWireBytes(); |
+ bytes_size = static_cast<size_t>(uncompiled_bytes->Length()); |
+ bytes = zone()->NewArray<uint8_t>(uncompiled_bytes->Length()); |
+ uncompiled_bytes->WriteOneByte(bytes); |
+ // keep alive data_ until the end |
+ data_ = v8_compiled_module->Serialize(); |
} |
- v8_isolate->Dispose(); |
+ |
+ wire_bytes_ = {const_cast<const uint8_t*>(bytes), bytes_size}; |
+ |
+ serialized_bytes_ = {data_.first.get(), data_.second}; |
+ |
+ v8::Isolate::CreateParams create_params; |
+ create_params.array_buffer_allocator = |
+ serialization_isolate->array_buffer_allocator(); |
+ |
+ current_isolate_v8_ = v8::Isolate::New(create_params); |
+ v8::HandleScope new_scope(current_isolate_v8()); |
+ v8::Local<v8::Context> deserialization_context = |
+ v8::Context::New(current_isolate_v8()); |
+ deserialization_context->Enter(); |
+ testing::SetupIsolateForWasmModule(current_isolate()); |
} |
+ |
+ void TearDown() { |
+ current_isolate_v8()->Dispose(); |
+ current_isolate_v8_ = nullptr; |
+ } |
+ |
+ v8::internal::AccountingAllocator allocator_; |
+ Zone zone_; |
+ v8::WasmCompiledModule::SerializedModule data_; |
+ v8::WasmCompiledModule::CallerOwnedBuffer wire_bytes_; |
+ v8::WasmCompiledModule::CallerOwnedBuffer serialized_bytes_; |
+ v8::Isolate* current_isolate_v8_; |
+}; |
+ |
+const char* WasmSerializationTest::kFunctionName = "increment"; |
+ |
+TEST(DeserializeValidModule) { |
+ WasmSerializationTest test; |
+ HandleScope scope(test.current_isolate()); |
+ test.DeserializeAndRun(); |
+} |
+ |
+TEST(DeserializeMismatchingVersion) { |
+ WasmSerializationTest test; |
+ HandleScope scope(test.current_isolate()); |
+ test.InvalidateVersion(); |
+ test.DeserializeAndRun(); |
+} |
+ |
+TEST(DeserializeNoSerializedData) { |
+ WasmSerializationTest test; |
+ HandleScope scope(test.current_isolate()); |
+ test.ClearSerializedData(); |
+ test.DeserializeAndRun(); |
+} |
+ |
+TEST(DeserializeWireBytesAndSerializedDataInvalid) { |
+ WasmSerializationTest test; |
+ HandleScope scope(test.current_isolate()); |
+ test.InvalidateVersion(); |
+ test.InvalidateWireBytes(); |
+ test.Deserialize(); |
} |
TEST(MemorySize) { |