Skip to content

Commit

Permalink
Merge branch 'master' into development/ipcchannel_dangling_handlers_t…
Browse files Browse the repository at this point in the history
…estcase
  • Loading branch information
msieben authored Sep 12, 2024
2 parents b02cbfd + f6e5980 commit e537c78
Show file tree
Hide file tree
Showing 12 changed files with 550 additions and 70 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/Build Documentation Preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
python-version: 3.x
- run: pip install mkdocs-material
- run: mkdocs build
- run: echo "${{ github.event.number }}" >> ./site/.pr_number
- run: echo "${{ github.event.number }}" >> ./site/pr_number
- name : Upload preview site artifact
uses : actions/upload-artifact@v4
with:
Expand All @@ -42,7 +42,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- run: mkdir pr_tmp
- run: echo "${{ github.event.number }}" >> ./pr_tmp/.pr_number
- run: echo "${{ github.event.number }}" >> ./pr_tmp/pr_number
- uses : actions/upload-artifact@v4
with:
name: closed_pr_number
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/Deploy Documentation Preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ jobs:
# Get PR number
- if: ${{ env.mode == 'deploy' }}
name: Get PR number (deploy)
run: echo "pr_number=$(cat ./artifacts/preview_site/.pr_number)" >> "$GITHUB_ENV"
run: echo "pr_number=$(cat ./artifacts/preview_site/pr_number)" >> "$GITHUB_ENV"

- if: ${{ env.mode == 'clean' }}
name: Get PR number (clean)
run: echo "pr_number=$(cat ./artifacts/closed_pr_number/.pr_number)" >> "$GITHUB_ENV"
run: echo "pr_number=$(cat ./artifacts/closed_pr_number/pr_number)" >> "$GITHUB_ENV"

# Run deployment
- if: ${{ env.mode == 'deploy' }}
Expand Down
2 changes: 1 addition & 1 deletion Tests/unit/IPTestAdministrator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ uint32_t IPTestAdministrator::Signal(uint32_t expectedNextHandshakeValue, uint8_
break;
default : result = ::Thunder::Core::ERROR_NONE;
// Atomically replaces the current value by the expected value
bool oldHandshakeValue = _sharedData->handshakeValue.exchange(expectedNextHandshakeValue);
VARIABLE_IS_NOT_USED bool oldHandshakeValue = _sharedData->handshakeValue.exchange(expectedNextHandshakeValue);
}

return result;
Expand Down
4 changes: 2 additions & 2 deletions Tests/unit/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ if(LINUX)
add_executable(${TEST_RUNNER_NAME}
../IPTestAdministrator.cpp
test_cyclicbuffer.cpp
# test_cyclicbuffer_dataexchange.cpp
test_cyclicbuffer_dataexchange.cpp
test_databuffer.cpp
test_dataelement.cpp
test_dataelementfile.cpp
Expand Down Expand Up @@ -74,7 +74,7 @@ add_executable(${TEST_RUNNER_NAME}
test_time.cpp
test_timer.cpp
test_tristate.cpp
test_valuerecorder.cpp
#test_valuerecorder.cpp
test_weblinkjson.cpp
test_weblinktext.cpp
test_websocketjson.cpp
Expand Down
132 changes: 75 additions & 57 deletions Tests/unit/core/test_cyclicbuffer_dataexchange.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,86 +19,104 @@

#include <gtest/gtest.h>

#include <future>
#ifndef MODULE_NAME
#include "../Module.h"
#endif

#include "../../cyclic-buffer/process.h"
#include <core/core.h>

#include "../IPTestAdministrator.h"

namespace WPEFramework {
namespace Core {
namespace Tests {

#define ASYNC_TIMEOUT_BEGIN \
std::promise<bool> promise; \
std::future<bool> future = promise.get_future(); \
std::thread([&](std::promise<bool> completed) \
{ /* Before code that should complete before timeout expires */

#define ASYNC_TIMEOUT_END(MILLISECONDS /* timeout in milliseconds */, EXPECTATION /* boolean */) \
/* After code that should complete timely */ \
/* completed.set_value(true); */ \
completed.set_value_at_thread_exit(true); \
} \
, std::move(promise)).detach() \
; \
bool result = future.wait_for(std::chrono::milliseconds(MILLISECONDS)) != std::future_status::timeout; /* Task completed before timeout */ \
EXPECT_TRUE(result == EXPECTATION); /* Task completed before timeout */ \
if (!result) { \
TRACE_L1(_T("Error : Stopping unresposive process.")); \
killpg(getpgrp(), SIGUSR1); /* Possible 'unresponsive' system, 'unlock' all related 'child' processes, default action is terminate */ \
}
TEST(Core_CyclicBuffer, DataExchange)
{
constexpr uint32_t initHandshakeValue = 0, maxWaitTime = 4, maxWaitTimeMs = 4000, maxInitTime = 2000;
constexpr uint8_t maxRetries = 1;

const std::string bufferName {"/tmp/SharedCyclicBuffer"};

constexpr uint32_t memoryMappedFileRequestedSize = 30;//446;

// https://en.wikipedia.org/wiki/Lorem_ipsum
#define LOREM_IPSUM_TEXT "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
const std::array<uint8_t, sizeof(LOREM_IPSUM_TEXT)> reference { "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." };

TEST(Core_CyclicBuffer, DataExchangeTimeout)
{
constexpr uint8_t maxChildren = 1;
IPTestAdministrator::Callback callback_child = [&](IPTestAdministrator& testAdmin) {
ASSERT_EQ(testAdmin.Wait(initHandshakeValue), ::Thunder::Core::ERROR_NONE);

constexpr uint32_t memoryMappedFileRequestedSize = 30;//446;
constexpr uint32_t internalBufferSize = 40;//446;
// Writer
Core::CyclicBuffer buffer { bufferName
, Core::File::USER_READ // Not relevant for readers
| Core::File::USER_WRITE // Open the existing file with write permission
// Readers normally require readonly but the cyclic buffer administration is updated after read
// | Core::File::CREATE // Readers access exisitng underlying memory mapped files
| Core::File::SHAREABLE // Updates are visible to other processes, but a reader should not update any content except when read data is (automatically) removed
, 0 // Readers do not specify sizes
, false // Overwrite unread data
};

constexpr char fileName[] = "/tmp/SharedCyclicBuffer";
ASSERT_TRUE( buffer.IsValid()
&& buffer.Open() // It already should
&& buffer.Storage().Name() == bufferName
&& Core::File(bufferName).Exists()
&& buffer.Storage().Exists()
);

constexpr uint32_t totalRuntime = Core::infinite; // Milliseconds
constexpr uint32_t timeout = 10000; // Milliseconds
ASSERT_EQ(buffer.Size(), memoryMappedFileRequestedSize);

WPEFramework::Tests::Process<memoryMappedFileRequestedSize, internalBufferSize, maxChildren> process(fileName);
uint32_t written = buffer.Write(reference.data(), std::min(sizeof(LOREM_IPSUM_TEXT), static_cast<size_t>(memoryMappedFileRequestedSize)) - 1);
EXPECT_EQ(written, std::min(sizeof(LOREM_IPSUM_TEXT), static_cast<size_t>(memoryMappedFileRequestedSize)) - 1);

ASYNC_TIMEOUT_BEGIN; // Avoid leaking resources, eg, children
ASSERT_EQ(testAdmin.Signal(initHandshakeValue, maxRetries), ::Thunder::Core::ERROR_NONE);
};

EXPECT_TRUE(process.SetTotalRuntime(totalRuntime)
&& process.SetNumReservedBlocks(2)
&& process.SetParentUsers(0, 0) /* 0 extra writer(s), 0 reader(s) */
&& process.SetChildUsers(0, 1) /* 1 writer(s), 1 reader(s) */
&& process.Execute()
);
IPTestAdministrator::Callback callback_parent = [&](IPTestAdministrator& testAdmin) {
// Writer
Core::CyclicBuffer buffer { bufferName
, Core::File::USER_READ // Enable read permissions on the underlying file for other users
| Core::File::USER_WRITE // Enable write permission on the underlying file
| Core::File::CREATE // Create a new underlying memory mapped file
| Core::File::SHAREABLE // Allow other processes to access the content of the file
, memoryMappedFileRequestedSize // Requested size
, false // Overwrite unread data
};

ASYNC_TIMEOUT_END(timeout, false /* expect no timeout */);
}
ASSERT_TRUE( buffer.IsValid()
&& buffer.Open() // It already should
&& buffer.Storage().Name() == bufferName
&& Core::File(bufferName).Exists()
&& buffer.Storage().Exists()
);

TEST(Core_CyclicBuffer, DataExchange)
{
constexpr uint8_t maxChildren = 1;
ASSERT_EQ(buffer.Size(), memoryMappedFileRequestedSize);

constexpr uint32_t memoryMappedFileRequestedSize = 30;//446;
constexpr uint32_t internalBufferSize = 40;//446;
std::array<uint8_t, sizeof(LOREM_IPSUM_TEXT) + 1> data;
data.fill('\0');

constexpr char fileName[] = "/tmp/SharedCyclicBuffer";
ASSERT_EQ(testAdmin.Signal(initHandshakeValue, maxRetries), ::Thunder::Core::ERROR_NONE);

constexpr uint32_t totalRuntime = 10000; // Milliseconds
constexpr uint32_t timeout = totalRuntime + 10000; // Milliseconds
ASSERT_EQ(testAdmin.Wait(initHandshakeValue), ::Thunder::Core::ERROR_NONE);

WPEFramework::Tests::Process<memoryMappedFileRequestedSize, internalBufferSize, maxChildren> process(fileName);
uint32_t read = buffer.Read(data.data(), std::min(sizeof(data), static_cast<size_t>(memoryMappedFileRequestedSize)) - 1);
EXPECT_EQ(read, std::min(sizeof(LOREM_IPSUM_TEXT), static_cast<size_t>(memoryMappedFileRequestedSize)) - 1);

ASYNC_TIMEOUT_BEGIN; // Avoid leaking resources, eg, children
bool result = true;
for(size_t index = 0; index < read; index++) {
result = result && reference[index] == data[index];
}

EXPECT_TRUE(process.SetTotalRuntime(totalRuntime)
&& process.SetNumReservedBlocks(2)
&& process.SetParentUsers(0, 0) /* 0 extra writer(s), 0 reader(s) */
&& process.SetChildUsers(0, 1) /* 1 writer(s), 1 reader(s) */
&& process.Execute()
);
EXPECT_TRUE(result);
};

ASYNC_TIMEOUT_END(timeout, true /* expect no timeout */);
}
IPTestAdministrator testAdmin(callback_parent, callback_child, initHandshakeValue, maxWaitTime);

// Code after this line is executed by both parent and child

::Thunder::Core::Singleton::Dispose();
}

} // Tests
} // Core
Expand Down
12 changes: 6 additions & 6 deletions Tests/unit/core/test_workerpool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -675,7 +675,7 @@ namespace Core {
const uint16_t scheduledTimes[] = {2000}; //In milliseconds
CheckWorkerPool_ScheduleJobs(1, 1, 0, 0, nullptr, scheduledTimes);
}
TEST(Core_WorkerPool, Check_ScheduleJobs_SinglePool_SingleJob_ZeroTime)
TEST(Core_WorkerPool, DISABLED_Check_ScheduleJobs_SinglePool_SingleJob_ZeroTime)
{
const uint16_t scheduledTimes[] = {0};
CheckWorkerPool_ScheduleJobs(1, 1, 0, 0, nullptr, scheduledTimes);
Expand Down Expand Up @@ -703,7 +703,7 @@ namespace Core {
const uint16_t scheduledTimes[] = {2000, 3000, 1000, 2000, 3000};
CheckWorkerPool_ScheduleJobs(1, maxJobs, 0, 0, nullptr, scheduledTimes);
}
TEST(Core_WorkerPool, Check_ScheduleJobs_SinglePool_MultipleJobs_ZeroTime)
TEST(Core_WorkerPool, DISABLED_Check_ScheduleJobs_SinglePool_MultipleJobs_ZeroTime)
{
uint8_t maxJobs = 5;
const uint16_t scheduledTimes[5] = {0};
Expand All @@ -724,7 +724,7 @@ namespace Core {
CheckWorkerPool_ScheduleJobs(2, maxJobs, 0, 0, nullptr, scheduledTimes);
CheckWorkerPool_ScheduleJobs(2, 2, 0, 0, nullptr, scheduledTimes);
}
TEST(Core_WorkerPool, Check_ScheduleJobs_MultiplePool_MultipleJobs_ZeroTime)
TEST(Core_WorkerPool, DISABLED_Check_ScheduleJobs_MultiplePool_MultipleJobs_ZeroTime)
{
uint8_t maxJobs = 5;
const uint16_t scheduledTimes[5] = {0};
Expand Down Expand Up @@ -829,7 +829,7 @@ namespace Core {
const uint16_t rescheduledTimes[] = {2000};
CheckWorkerPool_RescheduleJobs(1, 1, 0, 0, nullptr, scheduledTimes, rescheduledTimes);
}
TEST(Core_WorkerPool, Check_RescheduleJobs_SinglePool_SingleJob_ZeroTime)
TEST(Core_WorkerPool, DISABLED_Check_RescheduleJobs_SinglePool_SingleJob_ZeroTime)
{
const uint16_t scheduledTimes[] = {1000};
const uint16_t rescheduledTimes[] = {0};
Expand Down Expand Up @@ -863,7 +863,7 @@ namespace Core {
const uint16_t rescheduledTimes[] = {2000, 2000, 1000, 2000, 3000};
CheckWorkerPool_RescheduleJobs(1, 5, 0, 0, nullptr, scheduledTimes, rescheduledTimes);
}
TEST(Core_WorkerPool, Check_RescheduleJobs_SinglePool_MultipleJobs_ZeroTime)
TEST(Core_WorkerPool, DISABLED_Check_RescheduleJobs_SinglePool_MultipleJobs_ZeroTime)
{
const uint16_t scheduledTimes[] = {1000, 2000, 3000, 2000, 1000};
const uint16_t rescheduledTimes[5] = {0};
Expand Down Expand Up @@ -899,7 +899,7 @@ namespace Core {
const uint16_t rescheduledTimes[] = {2000, 2000, 1000, 2000, 3000};
CheckWorkerPool_RescheduleJobs(1, 5, 0, 0, nullptr, scheduledTimes, rescheduledTimes);
}
TEST(Core_WorkerPool, Check_RescheduleJobs_MultiplePool_MultipleJobs_ZeroTime)
TEST(Core_WorkerPool, DISABLED_Check_RescheduleJobs_MultiplePool_MultipleJobs_ZeroTime)
{
const uint16_t scheduledTimes[] = {1000, 2000, 3000, 2000, 1000};
const uint16_t rescheduledTimes[5] = {0};
Expand Down
Binary file added docs/assets/AsyncInterfaceExample.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/ExampleStaticDynamic1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/ExampleStaticDynamic2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
55 changes: 55 additions & 0 deletions docs/assets/umlsources.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
plantuml

@startuml

skin rose

participant Plugin order 30

Client1 -> Plugin: SetA(10)
CLient2 -> Plugin: GetA()
CLient2 -> Plugin: GetB()
Client1 -> Plugin: SetB(20)


@enduml


@startuml

skin rose

participant Plugin order 30

Client1 -> Plugin: SetA(10)
Activate Plugin
Plugin -> Client3: AChanged()
Activate Client3
Client2 -> Plugin: SetA(20)
Client3 -> Plugin: GetA()
Deactivate Client3
Plugin --> Client1
Deactivate Plugin

@enduml

@startuml

skin rose

participant Plugin order 30
participant PinProvider order 40

Client -> Plugin: GetPin(Callback)
Plugin --> Client
Plugin -> Plugin: GetPin
Activate Plugin
Plugin -> PinProvider: RetrievePin
Activate PinProvider
PinProvider --> Plugin: pin
Deactivate PinProvider
Plugin -> Client: Callback(pin)
Deactivate Plugin


@enduml
Loading

0 comments on commit e537c78

Please sign in to comment.