Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions tests/unit/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ add_subdirectory(aot-stack-frame)
add_subdirectory(linux-perf)
add_subdirectory(gc)
add_subdirectory(tid-allocator)
add_subdirectory(posix)

if (NOT WAMR_BUILD_TARGET STREQUAL "X86_32")
# should enable 32-bit llvm when X86_32
Expand Down
56 changes: 56 additions & 0 deletions tests/unit/posix/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Copyright (C) 2025 WAMR Community. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

cmake_minimum_required(VERSION 3.14)

project(test-posix-platform)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to consider how to manage situations where the host(or targeting) system isn't POSIX-like. My poor suggestion is something like:

if(UNIX AND NOT APPLE)
    message(STATUS "This is a POSIX-like system (Linux or similar).")
elseif(APPLE)
    message(STATUS "This is macOS, which is POSIX-compliant.")
else()
    message(STATUS "This is not a POSIX-like system.")
endif()

add_definitions(-DRUN_ON_LINUX)

set(WAMR_BUILD_LIBC_BUILTIN 1)
set(WAMR_BUILD_LIBC_WASI 1)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to open both. Or even any one.


include(../unit_common.cmake)

# Include paths
include_directories(${CMAKE_CURRENT_SOURCE_DIR})

# Step 6: posix_clock_test.cc, posix_sleep_test.cc, posix_time_test.cc, posix_malloc_test.cc, posix_file_test.cc, posix_socket_test.cc, and posix_blocking_op_test.cc
set(POSIX_TEST_SOURCE
${CMAKE_CURRENT_SOURCE_DIR}/posix_clock_test.cc
${CMAKE_CURRENT_SOURCE_DIR}/posix_sleep_test.cc
${CMAKE_CURRENT_SOURCE_DIR}/posix_time_test.cc
${CMAKE_CURRENT_SOURCE_DIR}/posix_malloc_test.cc
${CMAKE_CURRENT_SOURCE_DIR}/posix_file_test.cc
${CMAKE_CURRENT_SOURCE_DIR}/posix_socket_test.cc
${CMAKE_CURRENT_SOURCE_DIR}/posix_blocking_op_test.cc
)

# POSIX platform sources - Step 6: posix_clock.c, posix_sleep.c, posix_time.c, posix_malloc.c, posix_file.c, posix_socket.c, and posix_blocking_op.c
set(POSIX_PLATFORM_DIR ${WAMR_ROOT_DIR}/core/shared/platform/common/posix)
set(POSIX_SOURCE_FILES
${POSIX_PLATFORM_DIR}/posix_clock.c
${POSIX_PLATFORM_DIR}/posix_sleep.c
${POSIX_PLATFORM_DIR}/posix_time.c
${POSIX_PLATFORM_DIR}/posix_malloc.c
${POSIX_PLATFORM_DIR}/posix_file.c
${POSIX_PLATFORM_DIR}/posix_socket.c
${POSIX_PLATFORM_DIR}/posix_blocking_op.c
)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

POSIX_SOURCEF_FILES isn't necessary. should be removed.


# All sources for the test executable
set(unit_test_sources
${POSIX_TEST_SOURCE}
${POSIX_SOURCE_FILES}
${WAMR_RUNTIME_LIB_SOURCE}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WAMR_RUNTIME_LIB_SOURCE includes POSIX_SOURCE_FILES. L44 should be removed.

)

# Create test executable
add_executable(posix_platform_test ${unit_test_sources})
enable_testing()
include(GoogleTest)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

L50 and L51 are not necessary. unit_common.cmake includes that part.

# Link with Google Test
target_link_libraries(posix_platform_test gtest_main)

# Discover tests
gtest_discover_tests(posix_platform_test)
116 changes: 116 additions & 0 deletions tests/unit/posix/posix_blocking_op_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
* Copyright (C) 2025 WAMR Community. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/

#include "test_helper.h"
#include "gtest/gtest.h"
#include "platform_api_extension.h"
#include <unistd.h>
#include <sys/types.h>

class PosixBlockingOpTest : public testing::Test
{
protected:
virtual void SetUp()
{
// Initialize test environment
blocking_op_started = false;
}

virtual void TearDown()
{
// Cleanup
if (blocking_op_started) {
os_end_blocking_op();
blocking_op_started = false;
}
}

public:
WAMRRuntimeRAII<512 * 1024> runtime;
bool blocking_op_started;
};

// Step 3: Blocking Operations Tests for Coverage Improvement

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are ~6 functions in core/shared/platform/common/posix/posix_blocking_op.c, and the cases focus only on 2 of them. Since we aim to expand coverage quickly, it's preferable to create a few cases for each function rather than numerous cases for just one function.

TEST_F(PosixBlockingOpTest, BlockingOpInitialization)
{
// Test os_begin_blocking_op initialization
os_begin_blocking_op();
blocking_op_started = true;

// Test that we can call begin multiple times (should be idempotent)
os_begin_blocking_op();
// Verify the operation can be ended properly after multiple begins
EXPECT_NO_THROW(os_end_blocking_op());
}

TEST_F(PosixBlockingOpTest, BlockingOpCleanup)
{
// Start blocking operation first
os_begin_blocking_op();
blocking_op_started = true;

// Test os_end_blocking_op cleanup
os_end_blocking_op();
blocking_op_started = false;

// Test that ending again is safe (should be idempotent)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why should it be idempotent?

my impression is that this file is testing what the current implementation happens to be.
we should test the documented/defined functionality instead, IMO.

Copy link
Collaborator

@lum1n0us lum1n0us Sep 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should test the documented/defined functionality instead, IMO.

It will be in the next phase. Currently, this task is focusing on covering the code.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my point is that having these tests, especially with these comments, can give readers a wrong impression that it's a part of the API contract.

os_end_blocking_op();
SUCCEED() << "Multiple calls to os_end_blocking_op handled successfully";
}

TEST_F(PosixBlockingOpTest, BlockingOpCancelMechanism)
{
// Test blocking operation cancel functionality
os_begin_blocking_op();
blocking_op_started = true;

// Verify we can end the operation (simulates cancel)
EXPECT_NO_THROW(os_end_blocking_op());
blocking_op_started = false;
}



TEST_F(PosixBlockingOpTest, NestedBlockingOperations)
{
// Test nested blocking operations (should handle gracefully)
os_begin_blocking_op();
blocking_op_started = true;

// Try to start another blocking operation (should be handled)
os_begin_blocking_op();

// End operations in reverse order
os_end_blocking_op();
os_end_blocking_op();
blocking_op_started = false;
SUCCEED() << "Nested blocking operations handled successfully";
}

TEST_F(PosixBlockingOpTest, BlockingOpWithoutInit)
{
// Test ending blocking operation without starting it
os_end_blocking_op();
// Should handle gracefully (implementation dependent)
SUCCEED() << "End blocking operation without init handled gracefully";
}

TEST_F(PosixBlockingOpTest, BlockingOpStateConsistency)
{
// Test state consistency across multiple operations
for (int i = 0; i < 3; i++) {
os_begin_blocking_op();
blocking_op_started = true;

EXPECT_NO_THROW(os_end_blocking_op());
blocking_op_started = false;
}
}





122 changes: 122 additions & 0 deletions tests/unit/posix/posix_clock_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* Copyright (C) 2025 WAMR Community. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/

#include "test_helper.h"
#include "gtest/gtest.h"
#include "platform_api_extension.h"

class PosixClockTest : public testing::Test
{
protected:
virtual void SetUp() {}
virtual void TearDown() {}

public:
WAMRRuntimeRAII<512 * 1024> runtime;
};

TEST_F(PosixClockTest, ClockResolutionGet_ValidClocks)
{
__wasi_timestamp_t resolution;

// Test MONOTONIC clock
EXPECT_EQ(__WASI_ESUCCESS,
os_clock_res_get(__WASI_CLOCK_MONOTONIC, &resolution));
EXPECT_GT(resolution, 0);

// Test REALTIME clock
EXPECT_EQ(__WASI_ESUCCESS,
os_clock_res_get(__WASI_CLOCK_REALTIME, &resolution));
EXPECT_GT(resolution, 0);

// Test PROCESS_CPUTIME_ID clock if supported
__wasi_errno_t result =
os_clock_res_get(__WASI_CLOCK_PROCESS_CPUTIME_ID, &resolution);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The result will be influenced by the compilation flag CLOCK_PROCESS_CPUTIME_ID. How should we address that? It is better not enable both assertions at L38 and L41 at the same time.

if (result == __WASI_ESUCCESS) {
EXPECT_GT(resolution, 0);
}
else {
EXPECT_EQ(__WASI_ENOTSUP, result);
}

// Test THREAD_CPUTIME_ID clock if supported
result = os_clock_res_get(__WASI_CLOCK_THREAD_CPUTIME_ID, &resolution);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above.

if (result == __WASI_ESUCCESS) {
EXPECT_GT(resolution, 0);
}
else {
EXPECT_EQ(__WASI_ENOTSUP, result);
}
}

TEST_F(PosixClockTest, ClockTimeGet_ValidClocks)
{
__wasi_timestamp_t time1, time2;

// Test MONOTONIC clock
EXPECT_EQ(__WASI_ESUCCESS,
os_clock_time_get(__WASI_CLOCK_MONOTONIC, 0, &time1));
EXPECT_EQ(__WASI_ESUCCESS,
os_clock_time_get(__WASI_CLOCK_MONOTONIC, 0, &time2));
EXPECT_GE(time2, time1);

// Test REALTIME clock
EXPECT_EQ(__WASI_ESUCCESS,
os_clock_time_get(__WASI_CLOCK_REALTIME, 0, &time1));
EXPECT_GT(time1, 0);

// Test with different precision values
EXPECT_EQ(__WASI_ESUCCESS,
os_clock_time_get(__WASI_CLOCK_REALTIME, 1000000, &time1));
EXPECT_GT(time1, 0);
}

TEST_F(PosixClockTest, ClockTimeGet_InvalidClock)
{
__wasi_timestamp_t time;

// Test invalid clock ID
EXPECT_EQ(__WASI_EINVAL,
os_clock_time_get((__wasi_clockid_t)999, 0, &time));
}

TEST_F(PosixClockTest, ClockResolutionGet_InvalidClock)
{
__wasi_timestamp_t resolution;

// Test invalid clock ID
EXPECT_EQ(__WASI_EINVAL,
os_clock_res_get((__wasi_clockid_t)999, &resolution));
}

TEST_F(PosixClockTest, ClockTimeGet_ProcessCpuTime)
{
__wasi_timestamp_t time;

// Test PROCESS_CPUTIME_ID clock
__wasi_errno_t result =
os_clock_time_get(__WASI_CLOCK_PROCESS_CPUTIME_ID, 0, &time);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

if (result == __WASI_ESUCCESS) {
EXPECT_GE(time, 0);
}
else {
EXPECT_EQ(__WASI_ENOTSUP, result);
}
}

TEST_F(PosixClockTest, ClockTimeGet_ThreadCpuTime)
{
__wasi_timestamp_t time;

// Test THREAD_CPUTIME_ID clock
__wasi_errno_t result =
os_clock_time_get(__WASI_CLOCK_THREAD_CPUTIME_ID, 0, &time);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

if (result == __WASI_ESUCCESS) {
EXPECT_GE(time, 0);
}
else {
EXPECT_EQ(__WASI_ENOTSUP, result);
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMM,

  • static __wasi_errno_t wasi_clockid_to_clockid(__wasi_clockid_t in, clockid_t *out) and static __wasi_timestamp_t timespec_to_nanoseconds(const struct timespec *ts) should be called directly rather than through other functions.
  • It seems the cases attempt to cover edge scenarios but mostly fall short. A quick way to cover corners is to prepare values based on the argument types, such as using 0, negative values, positive values, INT32_MIN, and INT32_MAX for int32_t types. However, this approach resembles using a test plan.
  • If increasing coverage is not the plan, perhaps fewer cases will suffice.

Loading
Loading