Skip to content

Commit

Permalink
capi: Add rich error reporting to fizzy_resolve_instantiate
Browse files Browse the repository at this point in the history
  • Loading branch information
gumb0 committed Mar 31, 2021
1 parent a33e958 commit 528b0dd
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 20 deletions.
4 changes: 3 additions & 1 deletion include/fizzy/fizzy.h
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,8 @@ FizzyInstance* fizzy_instantiate(const FizzyModule* module,
/// @param imported_globals Pointer to the imported globals array. Can be NULL iff
/// @p imported_globals_size equals 0.
/// @param imported_globals_size Size of the imported global array. Can be zero.
/// @param error Pointer to store detailed error information at. Can be NULL
/// if error information is not required.
/// @return non-NULL pointer to instance in case of success,
/// NULL otherwise.
///
Expand All @@ -462,7 +464,7 @@ FizzyInstance* fizzy_instantiate(const FizzyModule* module,
FizzyInstance* fizzy_resolve_instantiate(const FizzyModule* module,
const FizzyImportedFunction* imported_functions, size_t imported_functions_size,
const FizzyExternalTable* imported_table, const FizzyExternalMemory* imported_memory,
const FizzyImportedGlobal* imported_globals, size_t imported_globals_size);
const FizzyImportedGlobal* imported_globals, size_t imported_globals_size, FizzyError* error);

/// Free resources associated with the instance.
///
Expand Down
4 changes: 3 additions & 1 deletion lib/fizzy/capi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,7 @@ FizzyInstance* fizzy_instantiate(const FizzyModule* module,
FizzyInstance* fizzy_resolve_instantiate(const FizzyModule* c_module,
const FizzyImportedFunction* c_imported_functions, size_t imported_functions_size,
const FizzyExternalTable* imported_table, const FizzyExternalMemory* imported_memory,
const FizzyImportedGlobal* c_imported_globals, size_t imported_globals_size)
const FizzyImportedGlobal* c_imported_globals, size_t imported_globals_size, FizzyError* error)
{
try
{
Expand All @@ -643,10 +643,12 @@ FizzyInstance* fizzy_resolve_instantiate(const FizzyModule* c_module,
auto instance = fizzy::instantiate(std::move(module), std::move(resolved_imports),
std::move(table), std::move(memory), std::move(resolved_globals));

set_success(error);
return wrap(instance.release());
}
catch (...)
{
set_error_from_current_exception(error);
return nullptr;
}
}
Expand Down
76 changes: 59 additions & 17 deletions test/unittests/capi_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -837,18 +837,35 @@ TEST(capi, resolve_instantiate_no_imports)
auto module = fizzy_parse(wasm.data(), wasm.size(), nullptr);
ASSERT_NE(module, nullptr);

auto instance = fizzy_resolve_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0);
// Success omitting FizzyError argument.
auto instance =
fizzy_resolve_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr);
EXPECT_NE(instance, nullptr);

fizzy_free_instance(instance);

module = fizzy_parse(wasm.data(), wasm.size(), nullptr);
ASSERT_NE(module, nullptr);

// Success with FizzyError argument.
FizzyError success;
instance =
fizzy_resolve_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0, &success);
EXPECT_NE(instance, nullptr);
EXPECT_EQ(success.code, FIZZY_SUCCESS);
EXPECT_STREQ(success.message, "");

fizzy_free_instance(instance);

module = fizzy_parse(wasm.data(), wasm.size(), nullptr);
ASSERT_NE(module, nullptr);

// providing unnecessary import
FizzyImportedFunction host_funcs[] = {
{"mod", "foo", {{FizzyValueTypeVoid, nullptr, 0}, NullFn, nullptr}}};

instance = fizzy_resolve_instantiate(module, host_funcs, 1, nullptr, nullptr, nullptr, 0);
instance =
fizzy_resolve_instantiate(module, host_funcs, 1, nullptr, nullptr, nullptr, 0, nullptr);
EXPECT_NE(instance, nullptr);

fizzy_free_instance(instance);
Expand All @@ -873,7 +890,20 @@ TEST(capi, resolve_instantiate_functions)
FizzyValue mod1g1value{42};
FizzyImportedGlobal mod1g1 = {"mod1", "g1", {&mod1g1value, {FizzyValueTypeI32, false}}};

EXPECT_EQ(fizzy_resolve_instantiate(module, nullptr, 0, nullptr, nullptr, &mod1g1, 1), nullptr);
// no functions provided
// Error omitting FizzyError argument.
EXPECT_EQ(fizzy_resolve_instantiate(module, nullptr, 0, nullptr, nullptr, &mod1g1, 1, nullptr),
nullptr);

module = fizzy_parse(wasm.data(), wasm.size(), nullptr);
ASSERT_NE(module, nullptr);

// Error with FizzyError argument.
FizzyError error;
EXPECT_EQ(fizzy_resolve_instantiate(module, nullptr, 0, nullptr, nullptr, &mod1g1, 1, &error),
nullptr);
EXPECT_EQ(error.code, FIZZY_ERROR_INSTANTIATION);
EXPECT_STREQ(error.message, "imported function mod1.foo1 is required");

module = fizzy_parse(wasm.data(), wasm.size(), nullptr);
ASSERT_NE(module, nullptr);
Expand All @@ -898,7 +928,8 @@ TEST(capi, resolve_instantiate_functions)
FizzyImportedFunction host_funcs[] = {{"mod1", "foo1", mod1foo1}, {"mod1", "foo2", mod1foo2},
{"mod2", "foo1", mod2foo1}, {"mod2", "foo2", mod2foo2}};

auto instance = fizzy_resolve_instantiate(module, host_funcs, 4, nullptr, nullptr, &mod1g1, 1);
auto instance =
fizzy_resolve_instantiate(module, host_funcs, 4, nullptr, nullptr, &mod1g1, 1, nullptr);
ASSERT_NE(instance, nullptr);

FizzyValue arg;
Expand All @@ -914,8 +945,8 @@ TEST(capi, resolve_instantiate_functions)
ASSERT_NE(module, nullptr);
FizzyImportedFunction host_funcs_reordered[] = {{"mod1", "foo2", mod1foo2},
{"mod2", "foo1", mod2foo1}, {"mod2", "foo2", mod2foo2}, {"mod1", "foo1", mod1foo1}};
instance =
fizzy_resolve_instantiate(module, host_funcs_reordered, 4, nullptr, nullptr, &mod1g1, 1);
instance = fizzy_resolve_instantiate(
module, host_funcs_reordered, 4, nullptr, nullptr, &mod1g1, 1, nullptr);
EXPECT_NE(instance, nullptr);
fizzy_free_instance(instance);

Expand All @@ -925,15 +956,19 @@ TEST(capi, resolve_instantiate_functions)
FizzyImportedFunction host_funcs_extra[] = {{"mod1", "foo1", mod1foo1},
{"mod1", "foo2", mod1foo2}, {"mod2", "foo1", mod2foo1}, {"mod2", "foo2", mod2foo2},
{"mod3", "foo1", mod1foo1}};
instance = fizzy_resolve_instantiate(module, host_funcs_extra, 4, nullptr, nullptr, &mod1g1, 1);
instance = fizzy_resolve_instantiate(
module, host_funcs_extra, 4, nullptr, nullptr, &mod1g1, 1, nullptr);
EXPECT_NE(instance, nullptr);
fizzy_free_instance(instance);

// not enough functions
module = fizzy_parse(wasm.data(), wasm.size(), nullptr);
ASSERT_NE(module, nullptr);
EXPECT_EQ(
fizzy_resolve_instantiate(module, host_funcs, 3, nullptr, nullptr, &mod1g1, 1), nullptr);
fizzy_resolve_instantiate(module, host_funcs, 3, nullptr, nullptr, &mod1g1, 1, &error),
nullptr);
EXPECT_EQ(error.code, FIZZY_ERROR_INSTANTIATION);
EXPECT_STREQ(error.message, "imported function mod2.foo2 is required");
}

TEST(capi, resolve_instantiate_function_duplicate)
Expand All @@ -954,7 +989,8 @@ TEST(capi, resolve_instantiate_function_duplicate)
FizzyExternalFunction mod1foo1 = {{FizzyValueTypeI32, nullptr, 0}, host_fn, nullptr};
FizzyImportedFunction host_funcs[] = {{"mod1", "foo1", mod1foo1}};

auto instance = fizzy_resolve_instantiate(module, host_funcs, 1, nullptr, nullptr, nullptr, 0);
auto instance =
fizzy_resolve_instantiate(module, host_funcs, 1, nullptr, nullptr, nullptr, 0, nullptr);
ASSERT_NE(instance, nullptr);

EXPECT_THAT(fizzy_execute(instance, 0, nullptr), CResult(42_u32));
Expand Down Expand Up @@ -983,7 +1019,11 @@ TEST(capi, resolve_instantiate_globals)
auto module = fizzy_parse(wasm.data(), wasm.size(), nullptr);
ASSERT_NE(module, nullptr);

EXPECT_EQ(fizzy_resolve_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0), nullptr);
FizzyError error;
EXPECT_EQ(fizzy_resolve_instantiate(module, nullptr, 0, nullptr, nullptr, nullptr, 0, &error),
nullptr);
EXPECT_EQ(error.code, FIZZY_ERROR_INSTANTIATION);
EXPECT_STREQ(error.message, "imported function mod1.foo1 is required");

module = fizzy_parse(wasm.data(), wasm.size(), nullptr);
ASSERT_NE(module, nullptr);
Expand All @@ -1007,7 +1047,7 @@ TEST(capi, resolve_instantiate_globals)
{"mod2", "g1", mod2g1}, {"mod2", "g2", mod2g2}};

auto instance =
fizzy_resolve_instantiate(module, &mod1foo1, 1, nullptr, nullptr, host_globals, 4);
fizzy_resolve_instantiate(module, &mod1foo1, 1, nullptr, nullptr, host_globals, 4, nullptr);
ASSERT_NE(instance, nullptr);

EXPECT_THAT(fizzy_execute(instance, 1, nullptr), CResult(42_u32));
Expand All @@ -1023,7 +1063,7 @@ TEST(capi, resolve_instantiate_globals)
FizzyImportedGlobal host_globals_reordered[] = {{"mod1", "g2", mod1g2}, {"mod2", "g1", mod2g1},
{"mod2", "g2", mod2g2}, {"mod1", "g1", mod1g1}};
instance = fizzy_resolve_instantiate(
module, &mod1foo1, 1, nullptr, nullptr, host_globals_reordered, 4);
module, &mod1foo1, 1, nullptr, nullptr, host_globals_reordered, 4, nullptr);
EXPECT_NE(instance, nullptr);

EXPECT_THAT(fizzy_execute(instance, 1, nullptr), CResult(42_u32));
Expand All @@ -1038,8 +1078,8 @@ TEST(capi, resolve_instantiate_globals)
ASSERT_NE(module, nullptr);
FizzyImportedGlobal host_globals_extra[] = {{"mod1", "g1", mod1g1}, {"mod1", "g2", mod1g2},
{"mod2", "g1", mod2g1}, {"mod2", "g2", mod2g2}, {"mod3", "g1", mod1g1}};
instance =
fizzy_resolve_instantiate(module, &mod1foo1, 1, nullptr, nullptr, host_globals_extra, 4);
instance = fizzy_resolve_instantiate(
module, &mod1foo1, 1, nullptr, nullptr, host_globals_extra, 4, nullptr);
EXPECT_NE(instance, nullptr);

EXPECT_THAT(fizzy_execute(instance, 1, nullptr), CResult(42_u32));
Expand All @@ -1052,9 +1092,11 @@ TEST(capi, resolve_instantiate_globals)
// not enough globals
module = fizzy_parse(wasm.data(), wasm.size(), nullptr);
ASSERT_NE(module, nullptr);
EXPECT_EQ(
fizzy_resolve_instantiate(module, &mod1foo1, 1, nullptr, nullptr, host_globals_extra, 3),
EXPECT_EQ(fizzy_resolve_instantiate(
module, &mod1foo1, 1, nullptr, nullptr, host_globals_extra, 3, &error),
nullptr);
EXPECT_EQ(error.code, FIZZY_ERROR_INSTANTIATION);
EXPECT_STREQ(error.message, "imported global mod2.g2 is required");
}

TEST(capi, resolve_instantiate_global_duplicate)
Expand All @@ -1077,7 +1119,7 @@ TEST(capi, resolve_instantiate_global_duplicate)
FizzyImportedGlobal host_globals[] = {{"mod1", "g1", mod1g1}};

auto instance =
fizzy_resolve_instantiate(module, nullptr, 0, nullptr, nullptr, host_globals, 1);
fizzy_resolve_instantiate(module, nullptr, 0, nullptr, nullptr, host_globals, 1, nullptr);
ASSERT_NE(instance, nullptr);

EXPECT_THAT(fizzy_execute(instance, 0, nullptr), CResult(42_u32));
Expand Down
3 changes: 2 additions & 1 deletion test/utils/fizzy_c_engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ bool FizzyCEngine::instantiate(bytes_view wasm_binary)
FizzyValueType inputs[] = {FizzyValueTypeI32, FizzyValueTypeI32};
FizzyImportedFunction imports[] = {
{"env", "adler32", {{FizzyValueTypeI32, inputs, 2}, env_adler32, nullptr}}};
m_instance.reset(fizzy_resolve_instantiate(module, imports, 1, nullptr, nullptr, nullptr, 0));
m_instance.reset(
fizzy_resolve_instantiate(module, imports, 1, nullptr, nullptr, nullptr, 0, nullptr));

return (m_instance != nullptr);
}
Expand Down

0 comments on commit 528b0dd

Please sign in to comment.