Skip to content

Commit c3e64d9

Browse files
committed
add AI-generated unit cases for constant value
Signed-off-by: zhenweijin <zhenwei.jin@intel.com> Co-authored-by: ai-assistant
1 parent d7459e8 commit c3e64d9

20 files changed

+1691
-0
lines changed

tests/unit/smart-tests/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,7 @@
22
cmake_minimum_required(VERSION 3.12)
33

44
add_subdirectory(interpreter)
5+
6+
if (NOT WAMR_BUILD_TARGET STREQUAL "X86_32")
7+
add_subdirectory(constants)
8+
endif ()
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
# Copyright (C) 2019 Intel Corporation. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
cmake_minimum_required(VERSION 3.14)
5+
6+
project(enhanced_constants_test)
7+
8+
# Platform-specific definitions
9+
add_definitions(-DRUN_ON_LINUX)
10+
add_definitions(-DWASM_ENABLE_WAMR_COMPILER=1)
11+
12+
set(WAMR_BUILD_INTERP 1)
13+
set(WAMR_BUILD_AOT 1)
14+
set(WAMR_BUILD_JIT 1)
15+
set(WAMR_BUILD_FAST_JIT 0)
16+
set(WAMR_BUILD_LIBC_WASI 1)
17+
set(WAMR_BUILD_APP_FRAMEWORK 0)
18+
set(WAMR_BUILD_MEMORY_PROFILING 0)
19+
20+
# Include shared unit test configuration
21+
include(../../unit_common.cmake)
22+
23+
find_package(LLVM REQUIRED CONFIG)
24+
include_directories(${LLVM_INCLUDE_DIRS})
25+
add_definitions(${LLVM_DEFINITIONS})
26+
27+
include(${IWASM_DIR}/compilation/iwasm_compl.cmake)
28+
29+
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
30+
31+
set(i32_const_test_sources
32+
enhanced_i32_const_test.cc
33+
${WAMR_RUNTIME_LIB_SOURCE}
34+
${IWASM_COMPL_SOURCE}
35+
${UNCOMMON_SHARED_SOURCE}
36+
)
37+
38+
# Prepare unit test sources for i64.const test
39+
# set(i64_const_test_sources
40+
# enhanced_i64_const_test.cc
41+
# ${WAMR_RUNTIME_LIB_SOURCE}
42+
# ${IWASM_COMPL_SOURCE}
43+
# ${UNCOMMON_SHARED_SOURCE}
44+
# )
45+
46+
# Prepare unit test sources for f32.const test
47+
set(f32_const_test_sources
48+
enhanced_f32_const_test.cc
49+
${WAMR_RUNTIME_LIB_SOURCE}
50+
${IWASM_COMPL_SOURCE}
51+
${UNCOMMON_SHARED_SOURCE}
52+
)
53+
54+
# Prepare unit test sources for f64.const test
55+
# set(f64_const_test_sources
56+
# enhanced_f64_const_test.cc
57+
# ${WAMR_RUNTIME_LIB_SOURCE}
58+
# ${IWASM_COMPL_SOURCE}
59+
# ${UNCOMMON_SHARED_SOURCE}
60+
# )
61+
62+
# Create test executables
63+
add_executable(enhanced_i32_const_test ${i32_const_test_sources})
64+
# add_executable(enhanced_i64_const_test ${i64_const_test_sources})
65+
add_executable(enhanced_f32_const_test ${f32_const_test_sources})
66+
# add_executable(enhanced_f64_const_test ${f64_const_test_sources})
67+
68+
69+
# Link required libraries
70+
target_link_libraries(enhanced_i32_const_test ${LLVM_AVAILABLE_LIBS} gtest_main)
71+
# target_link_libraries(enhanced_i64_const_test ${LLVM_AVAILABLE_LIBS} gtest_main)
72+
target_link_libraries(enhanced_f32_const_test ${LLVM_AVAILABLE_LIBS} gtest_main)
73+
# target_link_libraries(enhanced_f64_const_test ${LLVM_AVAILABLE_LIBS} gtest_main)
74+
75+
# Post-build: Copy WASM test files to build directory for all tests
76+
add_custom_command(TARGET enhanced_i32_const_test POST_BUILD
77+
COMMAND ${CMAKE_COMMAND} -E copy_directory
78+
${CMAKE_CURRENT_SOURCE_DIR}/wasm-apps
79+
$<TARGET_FILE_DIR:enhanced_i32_const_test>/wasm-apps
80+
COMMENT "Copying WASM test files to i32_const test build directory"
81+
)
82+
83+
# add_custom_command(TARGET enhanced_i64_const_test POST_BUILD
84+
# COMMAND ${CMAKE_COMMAND} -E copy_directory
85+
# ${CMAKE_CURRENT_SOURCE_DIR}/wasm-apps
86+
# $<TARGET_FILE_DIR:enhanced_i64_const_test>/wasm-apps
87+
# COMMENT "Copying WASM test files to i64_const test build directory"
88+
# )
89+
90+
add_custom_command(TARGET enhanced_f32_const_test POST_BUILD
91+
COMMAND ${CMAKE_COMMAND} -E copy_directory
92+
${CMAKE_CURRENT_SOURCE_DIR}/wasm-apps
93+
$<TARGET_FILE_DIR:enhanced_f32_const_test>/wasm-apps
94+
COMMENT "Copying WASM test files to f32_const test build directory"
95+
)
96+
97+
# add_custom_command(TARGET enhanced_f64_const_test POST_BUILD
98+
# COMMAND ${CMAKE_COMMAND} -E copy_directory
99+
# ${CMAKE_CURRENT_SOURCE_DIR}/wasm-apps
100+
# $<TARGET_FILE_DIR:enhanced_f64_const_test>/wasm-apps
101+
# COMMENT "Copying WASM test files to f64_const test build directory"
102+
# )
103+
104+
include(GoogleTest)
105+
106+
gtest_discover_tests(enhanced_i32_const_test
107+
PROPERTIES RUN_SERIAL TRUE
108+
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
109+
110+
# gtest_discover_tests(enhanced_i64_const_test
111+
# PROPERTIES RUN_SERIAL TRUE
112+
# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
113+
114+
gtest_discover_tests(enhanced_f32_const_test
115+
PROPERTIES RUN_SERIAL TRUE
116+
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
117+
118+
# gtest_discover_tests(enhanced_f64_const_test
119+
# PROPERTIES RUN_SERIAL TRUE
120+
# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
/*
2+
* Copyright (C) 2019 Intel Corporation. All rights reserved.
3+
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4+
*/
5+
6+
#include <gtest/gtest.h>
7+
#include <cstdint>
8+
#include <cfloat>
9+
#include <cmath>
10+
#include <cstdlib>
11+
#include <unistd.h>
12+
#include <cstring>
13+
#include "test_helper.h"
14+
#include "wasm_runtime_common.h"
15+
#include "bh_read_file.h"
16+
17+
static std::string CWD;
18+
static std::string WASM_FILE;
19+
20+
static int app_argc;
21+
static char **app_argv;
22+
23+
/**
24+
* Test fixture for f32.const opcode validation
25+
*
26+
* This class provides comprehensive testing infrastructure for the f32.const WebAssembly opcode,
27+
* ensuring proper constant loading functionality across different execution modes (interpreter and AOT).
28+
* Tests validate that f32.const correctly pushes immediate 32-bit IEEE 754 floating-point values onto
29+
* the execution stack without consuming any stack operands. Includes comprehensive validation of
30+
* special IEEE 754 values including NaN, infinity, zero, subnormals, and boundary conditions.
31+
*/
32+
class F32ConstTest : public testing::TestWithParam<RunningMode>
33+
{
34+
protected:
35+
WAMRRuntimeRAII<> runtime;
36+
wasm_module_t module = nullptr;
37+
wasm_module_inst_t module_inst = nullptr;
38+
wasm_exec_env_t exec_env = nullptr;
39+
uint32_t buf_size, stack_size = 8092, heap_size = 8092;
40+
uint8_t *buf = nullptr;
41+
char error_buf[128] = { 0 };
42+
const char *exception = nullptr;
43+
44+
/**
45+
* Set up test environment for f32.const opcode testing
46+
*
47+
* Initializes WAMR runtime with appropriate configuration for testing f32.const operations.
48+
* Configures memory allocation, execution mode, and loads the f32.const test module.
49+
* Ensures proper runtime state before executing individual test cases.
50+
*/
51+
void SetUp() override
52+
{
53+
memset(error_buf, 0, sizeof(error_buf));
54+
55+
buf = (uint8_t *)bh_read_file_to_buffer(WASM_FILE.c_str(), &buf_size);
56+
ASSERT_NE(buf, nullptr) << "Failed to read WASM file: " << WASM_FILE;
57+
58+
module = wasm_runtime_load(buf, buf_size, error_buf, sizeof(error_buf));
59+
ASSERT_NE(module, nullptr) << "Failed to load WASM module: " << error_buf;
60+
61+
module_inst = wasm_runtime_instantiate(module, stack_size, heap_size, error_buf, sizeof(error_buf));
62+
ASSERT_NE(module_inst, nullptr) << "Failed to instantiate WASM module: " << error_buf;
63+
64+
wasm_runtime_set_running_mode(module_inst, GetParam());
65+
66+
exec_env = wasm_runtime_create_exec_env(module_inst, stack_size);
67+
ASSERT_NE(exec_env, nullptr) << "Failed to create execution environment";
68+
}
69+
70+
/**
71+
* Clean up test environment after f32.const opcode testing
72+
*
73+
* Performs proper cleanup of WASM module instances, modules, and runtime resources.
74+
* Ensures no memory leaks or resource conflicts between test cases.
75+
* Maintains clean test environment for subsequent test execution.
76+
*/
77+
void TearDown() override
78+
{
79+
if (exec_env != nullptr) {
80+
wasm_runtime_destroy_exec_env(exec_env);
81+
exec_env = nullptr;
82+
}
83+
if (module_inst != nullptr) {
84+
wasm_runtime_deinstantiate(module_inst);
85+
module_inst = nullptr;
86+
}
87+
if (module != nullptr) {
88+
wasm_runtime_unload(module);
89+
module = nullptr;
90+
}
91+
if (buf != nullptr) {
92+
wasm_runtime_free(buf);
93+
buf = nullptr;
94+
}
95+
}
96+
97+
/**
98+
* Execute f32.const test function and return the loaded constant value
99+
*
100+
* @param func_name Name of the WASM function to execute (must return f32)
101+
* @return The f32 constant value loaded by the function
102+
*/
103+
float call_const_func(const char* func_name)
104+
{
105+
wasm_function_inst_t func_inst = wasm_runtime_lookup_function(module_inst, func_name);
106+
EXPECT_NE(func_inst, nullptr) << "Failed to lookup function: " << func_name;
107+
108+
wasm_val_t results[1];
109+
wasm_val_t arguments[1]; // f32.const doesn't need arguments but declaring for consistency
110+
111+
bool success = wasm_runtime_call_wasm_a(exec_env, func_inst, 1, results, 0, arguments);
112+
EXPECT_TRUE(success) << "Failed to call function: " << func_name
113+
<< ", exception: " << wasm_runtime_get_exception(module_inst);
114+
115+
return results[0].of.f32;
116+
}
117+
118+
/**
119+
* Execute multiple f32.const test function and return the loaded constant values
120+
*
121+
* @param func_name Name of the WASM function to execute (must return multiple f32 values)
122+
* @param result_count Number of f32 values to expect
123+
* @param results Array to store the returned f32 constant values
124+
*/
125+
void call_multi_const_func(const char* func_name, uint32_t result_count, float* results)
126+
{
127+
wasm_function_inst_t func_inst = wasm_runtime_lookup_function(module_inst, func_name);
128+
ASSERT_NE(func_inst, nullptr) << "Failed to lookup function: " << func_name;
129+
130+
wasm_val_t wasm_results[16]; // Sufficient for multiple constants
131+
wasm_val_t arguments[1]; // f32.const doesn't need arguments
132+
133+
bool success = wasm_runtime_call_wasm_a(exec_env, func_inst, result_count, wasm_results, 0, arguments);
134+
ASSERT_TRUE(success) << "Failed to call function: " << func_name
135+
<< ", exception: " << wasm_runtime_get_exception(module_inst);
136+
137+
for (uint32_t i = 0; i < result_count; i++) {
138+
results[i] = wasm_results[i].of.f32;
139+
}
140+
}
141+
142+
/**
143+
* Check if two f32 values are bitwise identical (handles NaN correctly)
144+
*
145+
* @param a First f32 value
146+
* @param b Second f32 value
147+
* @return true if bit patterns are identical, false otherwise
148+
*/
149+
bool are_f32_bitwise_equal(float a, float b)
150+
{
151+
uint32_t bits_a, bits_b;
152+
memcpy(&bits_a, &a, sizeof(uint32_t));
153+
memcpy(&bits_b, &b, sizeof(uint32_t));
154+
return bits_a == bits_b;
155+
}
156+
157+
/**
158+
* Get bit pattern of f32 value as uint32_t
159+
*
160+
* @param value f32 value to get bit pattern for
161+
* @return uint32_t representing the bit pattern
162+
*/
163+
uint32_t get_f32_bits(float value)
164+
{
165+
uint32_t bits;
166+
memcpy(&bits, &value, sizeof(uint32_t));
167+
return bits;
168+
}
169+
};
170+
171+
172+
173+
174+
/**
175+
* @test SpecialValues_PreservesIEEE754
176+
* @brief Validates f32.const preserves special IEEE 754 values correctly
177+
* @details Tests NaN, positive/negative infinity, positive/negative zero to ensure
178+
* f32.const correctly handles all special IEEE 754 single-precision values.
179+
* @test_category Edge - Special IEEE 754 value validation
180+
* @coverage_target core/iwasm/interpreter/wasm_interp_classic.c:f32_const_operation
181+
* @input_conditions NaN, +/-infinity, +/-zero IEEE 754 values
182+
* @expected_behavior Exact preservation of special values with correct IEEE 754 semantics
183+
* @validation_method Special value checks and bitwise comparison for signed zeros
184+
*/
185+
TEST_P(F32ConstTest, SpecialValues_PreservesIEEE754)
186+
{
187+
// Test NaN (Not-a-Number)
188+
float nan_result = call_const_func("get_nan");
189+
ASSERT_TRUE(std::isnan(nan_result))
190+
<< "f32.const failed to preserve NaN value";
191+
192+
// Test positive infinity
193+
ASSERT_TRUE(std::isinf(call_const_func("get_pos_inf")) && call_const_func("get_pos_inf") > 0)
194+
<< "f32.const failed to preserve positive infinity";
195+
196+
// Test negative infinity
197+
ASSERT_TRUE(std::isinf(call_const_func("get_neg_inf")) && call_const_func("get_neg_inf") < 0)
198+
<< "f32.const failed to preserve negative infinity";
199+
200+
// Test positive zero (0x00000000)
201+
float pos_zero = call_const_func("get_pos_zero");
202+
ASSERT_EQ(pos_zero, 0.0f) << "f32.const failed to load positive zero";
203+
ASSERT_EQ(get_f32_bits(pos_zero), 0x00000000U)
204+
<< "f32.const positive zero has incorrect bit pattern";
205+
206+
// Test negative zero (0x80000000)
207+
float neg_zero = call_const_func("get_neg_zero");
208+
ASSERT_EQ(neg_zero, -0.0f) << "f32.const failed to load negative zero";
209+
ASSERT_EQ(get_f32_bits(neg_zero), 0x80000000U)
210+
<< "f32.const negative zero has incorrect bit pattern";
211+
}
212+
213+
214+
215+
/**
216+
* @test ConstantsInOperations_FunctionsCorrectly
217+
* @brief Validates f32.const values work correctly in subsequent operations
218+
* @details Tests using f32.const values in f32.add operations to ensure constants
219+
* are properly loaded and available for arithmetic operations.
220+
* @test_category Integration - Constant usage in operations
221+
* @coverage_target core/iwasm/interpreter/wasm_interp_classic.c:f32_const_operation
222+
* @input_conditions f32.const values used as operands in f32.add
223+
* @expected_behavior Correct arithmetic results using loaded constants
224+
* @validation_method Verification of arithmetic operation results
225+
*/
226+
TEST_P(F32ConstTest, ConstantsInOperations_FunctionsCorrectly)
227+
{
228+
// Test f32.const 2.5 + f32.const 3.7 = 6.2
229+
ASSERT_EQ(call_const_func("add_two_constants"), 6.2f)
230+
<< "f32.const values failed in addition operation";
231+
232+
// Test f32.const 10.0 - f32.const 3.5 = 6.5
233+
ASSERT_EQ(call_const_func("subtract_constants"), 6.5f)
234+
<< "f32.const values failed in subtraction operation";
235+
236+
// Test f32.const 2.0 * f32.const 1.5 = 3.0
237+
ASSERT_EQ(call_const_func("multiply_constants"), 3.0f)
238+
<< "f32.const values failed in multiplication operation";
239+
}
240+
241+
// Parameterized test instantiation for both interpreter and AOT modes
242+
INSTANTIATE_TEST_SUITE_P(RunningModeTest, F32ConstTest,
243+
testing::Values(Mode_Interp, Mode_LLVM_JIT),
244+
[](const testing::TestParamInfo<F32ConstTest::ParamType> &info) {
245+
return info.param == Mode_Interp ? "INTERP" : "AOT";
246+
});
247+
248+
249+
int main(int argc, char **argv)
250+
{
251+
char *cwd = getcwd(nullptr, 0);
252+
if (cwd != nullptr) {
253+
CWD = std::string(cwd);
254+
free(cwd);
255+
} else {
256+
CWD = ".";
257+
}
258+
259+
WASM_FILE = CWD + "/wasm-apps/f32_const_test.wasm";
260+
261+
app_argc = argc;
262+
app_argv = argv;
263+
264+
::testing::InitGoogleTest(&argc, argv);
265+
return RUN_ALL_TESTS();
266+
}

0 commit comments

Comments
 (0)