Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
25bd7c9
Thunder IDL Tags — Additional Test Coverage
smanes0213 Jul 13, 2026
9de8f19
Merge branch 'master' into Development/Test-Thunder-Tags
smanes0213 Jul 13, 2026
4027e8e
Update ProxyStubFunctionalTests.yml
smanes0213 Jul 13, 2026
4208081
Update ProxyStubFunctionalTests.yml
smanes0213 Jul 13, 2026
496cd31
Split event tests into dedicated COM-RPC-only interface to avoid
smanes0213 Jul 13, 2026
adb6cd4
Resolve test failures
smanes0213 Jul 14, 2026
4eb04c2
Covering remaining gaps, update tests to use EXPECT_EQ isntead of find
smanes0213 Jul 14, 2026
e00d2d6
Covering remaining gaps, update tests to use EXPECT_EQ isntead of find
smanes0213 Jul 14, 2026
c21f535
Update ITestAnnotationEvent.h
smanes0213 Jul 14, 2026
2d9d901
Update TestAnnotationEventsImpl.cpp
smanes0213 Jul 14, 2026
a4a5862
Update TestAnnotationEventsImpl.cpp
smanes0213 Jul 14, 2026
9e88256
Update TestAnnotationEventsImpl.cpp
smanes0213 Jul 14, 2026
26574d4
Update TestAnnotationEvents.cpp
smanes0213 Jul 14, 2026
8663518
Update TestAnnotationEvents.cpp
smanes0213 Jul 14, 2026
ba2858a
Update TestAnnotationEventsImpl.cpp
smanes0213 Jul 14, 2026
4a2d74b
Update TestAnnotationEventsImpl.cpp
smanes0213 Jul 14, 2026
fde94ee
Update TestAnnotationEvents.cpp
smanes0213 Jul 14, 2026
f674db4
Update TestAnnotationEvents.cpp
smanes0213 Jul 14, 2026
70d2a5c
Update TestAnnotationEventsImpl.cpp
smanes0213 Jul 14, 2026
b498143
Update TestAnnotationEvents.cpp
smanes0213 Jul 14, 2026
509a34a
Update TestAnnotationEvents.cpp
smanes0213 Jul 14, 2026
cd7f432
Add tests for @prefix, @wrapped and JSON_RPC event subscription test
smanes0213 Jul 14, 2026
f3ad084
Resolve workflow failures
smanes0213 Jul 14, 2026
c9ff4ab
fix(ci): use per-architecture socket path to prevent parallel build i…
smanes0213 Jul 14, 2026
2ac64ea
Socket path is now configurable via COMRPC_SOCKET_PATH env variable
smanes0213 Jul 14, 2026
182e9c9
Resolve reveiew comments
smanes0213 Jul 15, 2026
6e130f7
Resolve test failure
smanes0213 Jul 15, 2026
d90e8ad
Resolve test failure
smanes0213 Jul 15, 2026
ad6bc60
Merge branch 'master' into Development/Test-Thunder-Tags
smanes0213 Jul 16, 2026
9da9516
Add more unit tests for @text tags
smanes0213 Jul 16, 2026
f72e3d2
Add more sleep time to resolve CI failure due to timeout
smanes0213 Jul 16, 2026
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
2 changes: 1 addition & 1 deletion .github/workflows/ProxyStubFunctionalTests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ on:
- "JsonGenerator/**"
- ".github/workflows/ProxyStubFunctionalTests.yml"
pull_request:
branches: [ master ]
branches: [ "master", "Development/Test-Thunder-Tags" ] #temp change
paths:
Comment thread
smanes0213 marked this conversation as resolved.
- "ProxyStubGenerator/**"
- "JsonGenerator/**"
Expand Down
5 changes: 5 additions & 0 deletions tests/FunctionalTests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ option(TEST_JSON_TEXT_CASE "Enable @text:legacy case convention tests"
option(TEST_JSON_COMPLIANT "Enable @compliant format tests" ON)
option(TEST_JSON_UNCOMPLIANT_EXT "Enable @uncompliant:extended format tests" ON)
option(TEST_JSON_UNCOMPLIANT_COL "Enable @uncompliant:collapsed format tests" ON)
option(TEST_ANNOTATIONS "Enable comprehensive annotation coverage tests" ON)
option(TEST_ANNOTATION_EVENTS "Enable @index on events + @statuslistener COM-RPC tests" ON)
option(TEST_EXTENDED_FORMAT "Enable @extended format semantics tests" ON)
option(TEST_PREFIX_UNDERSCORE "Enable @prefix with _ separator tests" ON)
option(TEST_WRAPPED_INTERFACE "Enable interface-level @wrapped tests" ON)

set(CMAKE_MODULE_PATH "${CMAKE_BINARY_DIR}" CACHE BOOL "" FORCE)

Expand Down
66 changes: 59 additions & 7 deletions tests/FunctionalTests/common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ target_link_libraries(FunctionalTestJsonSources
)

macro(AddTestInterface TestName)
cmake_parse_arguments(ARG "COM_RPC;JSON_RPC" "" "" ${ARGN})
cmake_parse_arguments(ARG "COM_RPC;JSON_RPC;HAS_EVENTS" "" "EVENT_HANDLERS" ${ARGN})

message(STATUS "Enabling ${TestName} test")

Expand All @@ -92,12 +92,44 @@ macro(AddTestInterface TestName)
if(ARG_JSON_RPC)
list(APPEND JSON_INTERFACE_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/interfaces/ITest${TestName}.h")


string(APPEND JSON_RPC_REGISTRATIONS
" FunctionalTest::JTest${TestName}::Register(module,\n"
" static_cast<FunctionalTest::ITest${TestName}*>(\n"
" TestImplementation::Factory::Instance().Create(FunctionalTest::ITest${TestName}::ID)));\n\n"
)
if(ARG_HAS_EVENTS)
# Event-bearing interfaces require a 3-parameter Register() call
# with an IHandler* for statuslistener / event dispatch.
# We provide a minimal no-op handler that satisfies the non-null assertion.
#
# EVENT_HANDLERS must list the statuslistener event names (e.g. "OnFeaturesChanged")
# so the generated NoOpHandler overrides the correct IHandler methods.
# The generated IHandler method name follows the pattern:
# On<EventName>EventRegistration(const string&, Status)
if(NOT ARG_EVENT_HANDLERS)
message(FATAL_ERROR "HAS_EVENTS requires EVENT_HANDLERS listing the statuslistener event names for ${TestName}")
endif()

set(_handler_overrides "")
foreach(_event ${ARG_EVENT_HANDLERS})
string(APPEND _handler_overrides
" void On${_event}EventRegistration(const string&, const PluginHost::JSONRPCSupportsEventStatus::Status) override {}\n"
)
endforeach()

string(APPEND JSON_RPC_REGISTRATIONS
" {\n"
" struct NoOpHandler : FunctionalTest::JTest${TestName}::IHandler {\n"
"${_handler_overrides}"
" };\n"
" static NoOpHandler handler;\n"
" auto* impl = static_cast<FunctionalTest::ITest${TestName}*>(\n"
" TestImplementation::Factory::Instance().Create(FunctionalTest::ITest${TestName}::ID));\n"
" FunctionalTest::JTest${TestName}::Register(module, impl, &handler);\n"
" }\n\n"
)
else()
string(APPEND JSON_RPC_REGISTRATIONS
" FunctionalTest::JTest${TestName}::Register(module,\n"
" static_cast<FunctionalTest::ITest${TestName}*>(\n"
" TestImplementation::Factory::Instance().Create(FunctionalTest::ITest${TestName}::ID)));\n\n"
)
endif()
string(APPEND JSON_RPC_UNREGISTRATIONS
" FunctionalTest::JTest${TestName}::Unregister(module);\n"
)
Expand Down Expand Up @@ -196,6 +228,26 @@ if (TEST_JSON_UNCOMPLIANT_COL)
AddTestInterface("JsonUncompliantCollapsed" COM_RPC JSON_RPC)
endif()

if (TEST_ANNOTATIONS)
AddTestInterface("Annotations" COM_RPC JSON_RPC HAS_EVENTS EVENT_HANDLERS "OnFeaturesChanged")
endif()

if (TEST_ANNOTATION_EVENTS)
AddTestInterface("AnnotationEvents" COM_RPC)
endif()

if (TEST_EXTENDED_FORMAT)
AddTestInterface("ExtendedFormat" COM_RPC JSON_RPC)
endif()

if (TEST_PREFIX_UNDERSCORE)
AddTestInterface("PrefixUnderscore" COM_RPC JSON_RPC)
endif()

if (TEST_WRAPPED_INTERFACE)
AddTestInterface("WrappedInterface" COM_RPC JSON_RPC)
endif()

list(LENGTH COM_RPC_INTERFACE_HEADERS NUM_COM_TESTS)
list(LENGTH JSON_INTERFACE_HEADERS NUM_JSON_TESTS)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*
* If not stated otherwise in this file or this component's LICENSE file the
* following copyright and licenses apply:
*
* Copyright 2026 Metrological
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <ImplementationFactory.h>
#include <ITestAnnotationEvents.h>
#include <mutex>
#include <thread>

namespace Thunder {
namespace TestImplementation {

class TestAnnotationEventsImpl : public FunctionalTest::ITestAnnotationEvents {
public:
TestAnnotationEventsImpl()
: _caps(FunctionalTest::ITestAnnotationEvents::CAP_NONE)
, _notification(nullptr)
{
}

~TestAnnotationEventsImpl() override = default;

TestAnnotationEventsImpl(const TestAnnotationEventsImpl&) = delete;
TestAnnotationEventsImpl& operator=(const TestAnnotationEventsImpl&) = delete;

Core::hresult Register(INotification* notification) override
{
std::lock_guard<std::mutex> lock(_mutex);
if (_notification != nullptr) {
return Core::ERROR_ALREADY_CONNECTED;
}
_notification = notification;
_notification->AddRef();
// @statuslistener: deliver current caps on a background thread to avoid
// COM-RPC channel deadlock (cannot make a reverse call on the same channel
// that is still processing the Register request).
Caps currentCaps = _caps;
INotification* sink = _notification;
sink->AddRef();
std::thread([sink, currentCaps]() {
sink->OnCapsChanged(currentCaps);
sink->Release();
}).detach();
return Core::ERROR_NONE;
}

Core::hresult Unregister(INotification* notification) override
{
std::lock_guard<std::mutex> lock(_mutex);
if (_notification == notification) {
_notification->Release();
_notification = nullptr;
return Core::ERROR_NONE;
}
return Core::ERROR_NOT_EXIST;
}

// All notification callbacks are dispatched on background threads to avoid
// COM-RPC channel deadlock. The server's worker thread cannot make a reverse-proxy
// call on the same channel it's currently serving a request on.

Core::hresult SetCaps(const Caps caps) override
{
_caps = caps;
std::lock_guard<std::mutex> lock(_mutex);
if (_notification) {
INotification* sink = _notification;
sink->AddRef();
Caps c = _caps;
std::thread([sink, c]() { sink->OnCapsChanged(c); sink->Release(); }).detach();
}
return Core::ERROR_NONE;
}

Core::hresult GetCaps(Caps& caps) const override
{
caps = _caps;
return Core::ERROR_NONE;
}

Core::hresult TriggerPortState(const uint8_t port, const State state) override
{
std::lock_guard<std::mutex> lock(_mutex);
if (_notification) {
INotification* sink = _notification;
sink->AddRef();
std::thread([sink, port, state]() { sink->OnPortStateChanged(port, state); sink->Release(); }).detach();
}
return Core::ERROR_NONE;
}

Core::hresult TriggerStatus(const string& message) override
{
std::lock_guard<std::mutex> lock(_mutex);
if (_notification) {
INotification* sink = _notification;
sink->AddRef();
string msg = message;
std::thread([sink, msg]() { sink->OnStatusUpdate(msg); sink->Release(); }).detach();
}
return Core::ERROR_NONE;
}

Core::hresult TriggerLegacyChannel(const uint8_t channel, const uint32_t level) override
{
std::lock_guard<std::mutex> lock(_mutex);
if (_notification) {
INotification* sink = _notification;
sink->AddRef();
std::thread([sink, channel, level]() { sink->OnLegacyChannelEvent(channel, level); sink->Release(); }).detach();
}
return Core::ERROR_NONE;
}

BEGIN_INTERFACE_MAP(TestAnnotationEventsImpl)
INTERFACE_ENTRY(FunctionalTest::ITestAnnotationEvents)
END_INTERFACE_MAP

private:
Caps _caps;
INotification* _notification;
mutable std::mutex _mutex;
};

static Factory::Registrar<FunctionalTest::ITestAnnotationEvents, TestAnnotationEventsImpl> g_annotationEventsRegistrar;

} // namespace TestImplementation
} // namespace Thunder
Loading
Loading