Skip to content
Merged
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
6 changes: 6 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,11 @@ jobs:
- name: Build AASDK for ${{ matrix.arch }} on ${{ matrix.distro }}
run: |
echo "Building AASDK for ${{ matrix.arch }} architecture"
RUN_TESTS=false
if [ "${{ github.event_name }}" = "pull_request" ] || [ "${{ github.ref }}" = "refs/heads/main" ] || [ "${{ github.ref }}" = "refs/heads/develop" ]; then
RUN_TESTS=true
fi
echo "RUN_TESTS=${RUN_TESTS} for this build"
if [ "${{ github.ref }}" = "refs/heads/main" ]; then
BUILD_TYPE="release"
echo "Building release packages for main branch"
Expand All @@ -196,6 +201,7 @@ jobs:
--build-arg TARGET_ARCH=${{ matrix.arch }} \
--build-arg DEBIAN_VERSION=${{ matrix.distro }} \
--build-arg BUILD_TYPE=${BUILD_TYPE} \
--build-arg RUN_TESTS=${RUN_TESTS} \
--tag aasdk-build:${{ matrix.arch }} \
--load \
.
Expand Down
6 changes: 5 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ endif()
# Paths
set(sources_directory ${CMAKE_CURRENT_SOURCE_DIR}/src)
set(include_directory ${CMAKE_CURRENT_SOURCE_DIR}/include)
set(include_ut_directory ${CMAKE_CURRENT_SOURCE_DIR}/include_ut)
set(include_ut_directory ${CMAKE_CURRENT_SOURCE_DIR}/unit_test)

# Set output directories to build directory for proper packaging
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib)
Expand Down Expand Up @@ -396,6 +396,8 @@ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/aasdk.pc"
COMPONENT development)

if(AASDK_TEST)
enable_testing()

add_executable(aasdk_ut
${tests_source_files}
${tests_include_files})
Expand All @@ -406,6 +408,8 @@ if(AASDK_TEST)
gtest_main
gmock_main)

add_test(NAME aasdk_ut COMMAND aasdk_ut)

if(AASDK_CODE_COVERAGE)
include(CodeCoverage)
append_coverage_compiler_flags()
Expand Down
6 changes: 5 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ FROM debian:${DEBIAN_VERSION}-slim
# Build arguments
ARG TARGET_ARCH=amd64
ARG BUILD_TYPE=release
ARG RUN_TESTS=false
ARG DEBIAN_FRONTEND=noninteractive
ARG GIT_COMMIT_ID=unknown
ARG GIT_BRANCH=unknown
Expand Down Expand Up @@ -102,8 +103,11 @@ RUN echo "=== Git environment variables before build ===" && \
echo " GIT_DESCRIBE=$GIT_DESCRIBE" && \
echo " GIT_COMMIT_TIMESTAMP=$GIT_COMMIT_TIMESTAMP" && \
echo " GIT_DIRTY=$GIT_DIRTY" && \
echo " RUN_TESTS=$RUN_TESTS" && \
echo "=============================================" && \
export TARGET_ARCH=$(dpkg-architecture -qDEB_HOST_ARCH) && \
TEST_ARG="" && \
if [ "$RUN_TESTS" = "true" ]; then TEST_ARG="test"; fi && \
echo "Building AASDK for architecture: $TARGET_ARCH (native compilation)" && \
# Compute distro-specific release suffix for DEB packages
DISTRO_DEB_RELEASE=$(bash /src/scripts/distro_release.sh) && \
Expand All @@ -112,7 +116,7 @@ RUN echo "=== Git environment variables before build ===" && \
# Pass through to CMake via build.sh using CMAKE_ARGS
env DISTRO_DEB_RELEASE="$CPACK_DEB_RELEASE" CMAKE_ARGS="$CMAKE_ARGS -DCPACK_DEBIAN_PACKAGE_RELEASE=$CPACK_DEB_RELEASE -DCPACK_PROJECT_CONFIG_FILE=/src/cmake_modules/CPackProjectConfig.cmake" \
CROSS_COMPILE=${CROSS_COMPILE} \
./build.sh ${BUILD_TYPE} clean package --skip-protobuf --skip-absl && \
./build.sh ${BUILD_TYPE} clean ${TEST_ARG} package --skip-protobuf --skip-absl && \
if [ -d "packages" ]; then \
cp packages/*.deb /output/ 2>/dev/null || true && \
echo "Packages built:" && \
Expand Down
155 changes: 151 additions & 4 deletions src/Messenger/MessageInStream.ut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
*/

#include <gtest/gtest.h>
#include <aap_protobuf/service/control/ControlMessageType.pb.h>
#include <aasdk/Messenger/MessageId.hpp>
#include <aasdk/Transport/UT/Transport.mock.hpp>
#include <aasdk/Messenger/UT/Cryptor.mock.hpp>
#include <aasdk/Messenger/UT/ReceivePromiseHandler.mock.hpp>
Expand Down Expand Up @@ -134,6 +136,7 @@ TEST_F(MessageInStreamUnitTest, MessageInStream_ReceiveEncryptedMessage)
EXPECT_CALL(transportMock_, receive(framePayload.size(), _)).WillOnce(SaveArg<1>(&framePayloadTransportPromise));

common::Data decryptedPayload(500, 0x5F);
ON_CALL(cryptorMock_, isActive()).WillByDefault(Return(true));
EXPECT_CALL(cryptorMock_, decrypt(_, _, _)).WillOnce(DoAll(SetArgReferee<0>(decryptedPayload), Return(decryptedPayload.size())));
frameSizeTransportPromise->resolve(frameSize.getData());

Expand Down Expand Up @@ -181,6 +184,7 @@ TEST_F(MessageInStreamUnitTest, MessageInStream_MessageDecryptionFailed)
EXPECT_CALL(transportMock_, receive(framePayload.size(), _)).WillOnce(SaveArg<1>(&framePayloadTransportPromise));

common::Data decryptedPayload(500, 0x5F);
ON_CALL(cryptorMock_, isActive()).WillByDefault(Return(true));
EXPECT_CALL(cryptorMock_, decrypt(_, _, _)).WillOnce(ThrowSSLReadException());
frameSizeTransportPromise->resolve(frameSize.getData());

Expand Down Expand Up @@ -350,13 +354,15 @@ TEST_F(MessageInStreamUnitTest, MessageInStream_ReceiveSplittedMessage)
EXPECT_THAT(payload, testing::ContainerEq(expectedPayload));
}

TEST_F(MessageInStreamUnitTest, MessageInStream_IntertwinedChannels)
TEST_F(MessageInStreamUnitTest, MessageInStream_IntertwinedChannelsContinueReceivingWithoutResolving)
{
MessageInStream::Pointer messageInStream(std::make_shared<MessageInStream>(ioService_, transport_, cryptor_));
FrameHeader frame1Header(ChannelId::BLUETOOTH, FrameType::FIRST, EncryptionType::PLAIN, MessageType::SPECIFIC);

transport::ITransport::ReceivePromise::Pointer frameHeaderTransportPromise;
EXPECT_CALL(transportMock_, receive(FrameHeader::getSizeOf(), _)).Times(2).WillRepeatedly(SaveArg<1>(&frameHeaderTransportPromise));
// FrameHeader::getSizeOf() == FrameSize::getSizeOf(SHORT) == 2, so all receive(2,_) calls
// (3 header reads + 1 SHORT frame-size read) must share a single unified expectation.
EXPECT_CALL(transportMock_, receive(FrameHeader::getSizeOf(), _)).Times(4).WillRepeatedly(SaveArg<1>(&frameHeaderTransportPromise));

messageInStream->startReceive(std::move(receivePromise_));

Expand Down Expand Up @@ -387,12 +393,153 @@ TEST_F(MessageInStreamUnitTest, MessageInStream_IntertwinedChannels)
ioService_.reset();

FrameHeader frame2Header(ChannelId::MEDIA_SINK_VIDEO, FrameType::LAST, EncryptionType::PLAIN, MessageType::SPECIFIC);
// Resolving frame2Header causes receiveFrameHeaderHandler to request the SHORT frame-size (2 bytes).
// frameHeaderTransportPromise is reused — after ioService_.run() it will point to the size promise.
frameHeaderTransportPromise->resolve(frame2Header.getData());

ioService_.run();
ioService_.reset();

EXPECT_CALL(receivePromiseHandlerMock_, onReject(error::Error(error::ErrorCode::MESSENGER_INTERTWINED_CHANNELS)));
transport::ITransport::ReceivePromise::Pointer frame2PayloadTransportPromise;
EXPECT_CALL(transportMock_, receive(frame2Payload.size(), _)).WillOnce(SaveArg<1>(&frame2PayloadTransportPromise));
FrameSize frame2Size(frame2Payload.size());
// frameHeaderTransportPromise now holds the SHORT frame-size promise (saved by WillRepeatedly above).
frameHeaderTransportPromise->resolve(frame2Size.getData());

ioService_.run();
ioService_.reset();

EXPECT_CALL(receivePromiseHandlerMock_, onReject(_)).Times(0);
EXPECT_CALL(receivePromiseHandlerMock_, onResolve(_)).Times(0);
frameHeaderTransportPromise->resolve(frame2Header.getData());
frame2PayloadTransportPromise->resolve(frame2Payload);

ioService_.run();
}

TEST_F(MessageInStreamUnitTest, MessageInStream_InactiveCryptorTlsControlPayloadGetsEncapsulatedSslPrefix)
{
MessageInStream::Pointer messageInStream(std::make_shared<MessageInStream>(ioService_, transport_, cryptor_));

FrameHeader frameHeader(ChannelId::CONTROL, FrameType::BULK, EncryptionType::ENCRYPTED, MessageType::CONTROL);
transport::ITransport::ReceivePromise::Pointer frameHeaderTransportPromise;
EXPECT_CALL(transportMock_, receive(FrameHeader::getSizeOf(), _)).WillOnce(SaveArg<1>(&frameHeaderTransportPromise));

messageInStream->startReceive(std::move(receivePromise_));

ioService_.run();
ioService_.reset();

common::Data framePayload{0x17, 0x03, 0x03, 0x00, 0x2A};
FrameSize frameSize(framePayload.size());
transport::ITransport::ReceivePromise::Pointer frameSizeTransportPromise;
EXPECT_CALL(transportMock_, receive(FrameSize::getSizeOf(FrameSizeType::SHORT), _)).WillOnce(SaveArg<1>(&frameSizeTransportPromise));
frameHeaderTransportPromise->resolve(frameHeader.getData());

ioService_.run();
ioService_.reset();

transport::ITransport::ReceivePromise::Pointer framePayloadTransportPromise;
EXPECT_CALL(transportMock_, receive(framePayload.size(), _)).WillOnce(SaveArg<1>(&framePayloadTransportPromise));
ON_CALL(cryptorMock_, isActive()).WillByDefault(Return(false));
EXPECT_CALL(cryptorMock_, decrypt(_, _, _)).Times(0);
frameSizeTransportPromise->resolve(frameSize.getData());

ioService_.run();
ioService_.reset();

Message::Pointer message;
EXPECT_CALL(receivePromiseHandlerMock_, onReject(_)).Times(0);
EXPECT_CALL(receivePromiseHandlerMock_, onResolve(_)).WillOnce(SaveArg<0>(&message));
framePayloadTransportPromise->resolve(framePayload);

ioService_.run();

common::Data expectedPayload = MessageId(
aap_protobuf::service::control::message::ControlMessageType::MESSAGE_ENCAPSULATED_SSL).getData();
expectedPayload.insert(expectedPayload.end(), framePayload.begin(), framePayload.end());
EXPECT_THAT(message->getPayload(), testing::ContainerEq(expectedPayload));
}

TEST_F(MessageInStreamUnitTest, MessageInStream_InactiveCryptorNonTlsControlPayloadPassesThroughRaw)
{
MessageInStream::Pointer messageInStream(std::make_shared<MessageInStream>(ioService_, transport_, cryptor_));

FrameHeader frameHeader(ChannelId::CONTROL, FrameType::BULK, EncryptionType::ENCRYPTED, MessageType::CONTROL);
transport::ITransport::ReceivePromise::Pointer frameHeaderTransportPromise;
EXPECT_CALL(transportMock_, receive(FrameHeader::getSizeOf(), _)).WillOnce(SaveArg<1>(&frameHeaderTransportPromise));

messageInStream->startReceive(std::move(receivePromise_));

ioService_.run();
ioService_.reset();

common::Data framePayload{0x01, 0x02, 0x03, 0x04};
FrameSize frameSize(framePayload.size());
transport::ITransport::ReceivePromise::Pointer frameSizeTransportPromise;
EXPECT_CALL(transportMock_, receive(FrameSize::getSizeOf(FrameSizeType::SHORT), _)).WillOnce(SaveArg<1>(&frameSizeTransportPromise));
frameHeaderTransportPromise->resolve(frameHeader.getData());

ioService_.run();
ioService_.reset();

transport::ITransport::ReceivePromise::Pointer framePayloadTransportPromise;
EXPECT_CALL(transportMock_, receive(framePayload.size(), _)).WillOnce(SaveArg<1>(&framePayloadTransportPromise));
ON_CALL(cryptorMock_, isActive()).WillByDefault(Return(false));
EXPECT_CALL(cryptorMock_, decrypt(_, _, _)).Times(0);
frameSizeTransportPromise->resolve(frameSize.getData());

ioService_.run();
ioService_.reset();

Message::Pointer message;
EXPECT_CALL(receivePromiseHandlerMock_, onReject(_)).Times(0);
EXPECT_CALL(receivePromiseHandlerMock_, onResolve(_)).WillOnce(SaveArg<0>(&message));
framePayloadTransportPromise->resolve(framePayload);

ioService_.run();

EXPECT_THAT(message->getPayload(), testing::ContainerEq(framePayload));
}

TEST_F(MessageInStreamUnitTest, MessageInStream_InactiveCryptorTlsVideoPayloadDoesNotSynthesizeControlMessageId)
{
MessageInStream::Pointer messageInStream(std::make_shared<MessageInStream>(ioService_, transport_, cryptor_));

FrameHeader frameHeader(ChannelId::MEDIA_SINK_VIDEO, FrameType::BULK, EncryptionType::ENCRYPTED, MessageType::SPECIFIC);
transport::ITransport::ReceivePromise::Pointer frameHeaderTransportPromise;
EXPECT_CALL(transportMock_, receive(FrameHeader::getSizeOf(), _)).WillOnce(SaveArg<1>(&frameHeaderTransportPromise));

messageInStream->startReceive(std::move(receivePromise_));

ioService_.run();
ioService_.reset();

common::Data framePayload{0x17, 0x03, 0x03, 0x00, 0x10};
FrameSize frameSize(framePayload.size());
transport::ITransport::ReceivePromise::Pointer frameSizeTransportPromise;
EXPECT_CALL(transportMock_, receive(FrameSize::getSizeOf(FrameSizeType::SHORT), _)).WillOnce(SaveArg<1>(&frameSizeTransportPromise));
frameHeaderTransportPromise->resolve(frameHeader.getData());

ioService_.run();
ioService_.reset();

transport::ITransport::ReceivePromise::Pointer framePayloadTransportPromise;
EXPECT_CALL(transportMock_, receive(framePayload.size(), _)).WillOnce(SaveArg<1>(&framePayloadTransportPromise));
ON_CALL(cryptorMock_, isActive()).WillByDefault(Return(false));
EXPECT_CALL(cryptorMock_, decrypt(_, _, _)).Times(0);
frameSizeTransportPromise->resolve(frameSize.getData());

ioService_.run();
ioService_.reset();

Message::Pointer message;
EXPECT_CALL(receivePromiseHandlerMock_, onReject(_)).Times(0);
EXPECT_CALL(receivePromiseHandlerMock_, onResolve(_)).WillOnce(SaveArg<0>(&message));
framePayloadTransportPromise->resolve(framePayload);

ioService_.run();

EXPECT_THAT(message->getPayload(), testing::ContainerEq(framePayload));
}

TEST_F(MessageInStreamUnitTest, MessageInStream_RejectWhenInProgress)
Expand Down
Loading