/*
* Copyright (C) 2020 Embedded AMS B.V. - All Rights Reserved
*
* This file is part of Embedded Proto.
*
* Embedded Proto is open source software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation, version 3 of the license.
*
* Embedded Proto is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Embedded Proto. If not, see .
*
* For commercial and closed source application please visit:
* .
*
* Embedded AMS B.V.
* Info:
* info at EmbeddedProto dot com
*
* Postal address:
* Johan Huizingalaan 763a
* 1066 VH, Amsterdam
* the Netherlands
*/
#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include
#include
#include
#include
#include
// EAMS message definitions
#include
using ::testing::_;
using ::testing::InSequence;
using ::testing::Return;
using ::testing::SetArgReferee;
using ::testing::ElementsAre;
namespace test_EmbeddedAMS_string_bytes
{
TEST(FieldString, clear)
{
text<10> msg;
// Clear the field specific.
msg.mutable_txt() = "Foo Bar";
EXPECT_EQ(7, msg.txt().get_length());
msg.clear_txt();
EXPECT_EQ(0, msg.txt().get_length());
// Clear the whole message.
msg.mutable_txt() = "Foo Bar";
msg.clear();
EXPECT_EQ(0, msg.txt().get_length());
}
TEST(FieldString, serialize)
{
InSequence s;
text<10> msg;
Mocks::WriteBufferMock buffer;
msg.mutable_txt() = "Foo bar";
EXPECT_CALL(buffer, get_available_size()).Times(1).WillOnce(Return(17));
uint8_t expected[] = {0x0a, 0x07};
for(auto e : expected)
{
EXPECT_CALL(buffer, push(e)).Times(1).WillOnce(Return(true));
}
EXPECT_CALL(buffer, push(_, 7)).Times(1).WillOnce(Return(true));
EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
EXPECT_EQ(10, msg.txt().get_max_length());
}
TEST(FieldString, deserialize)
{
InSequence s;
text<10> msg;
Mocks::ReadBufferMock buffer;
uint8_t referee[] = {0x0a, 0x07, 0x46, 0x6f, 0x6f, 0x20, 0x62, 0x61, 0x72};
for(auto r: referee)
{
EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(r), Return(true)));
}
EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(Return(false));
EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.deserialize(buffer));
EXPECT_EQ(7, msg.txt().get_length());
EXPECT_STREQ(msg.get_txt(), "Foo bar");
}
TEST(FieldString, deserialize_error_invalid_wiretype)
{
InSequence s;
text<10> msg;
Mocks::ReadBufferMock buffer;
// The first byte is an invalid wiretype
EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(0x09), Return(true)));
EXPECT_EQ(::EmbeddedProto::Error::INVALID_WIRETYPE, msg.deserialize(buffer));
EXPECT_EQ(0, msg.txt().get_length());
}
TEST(FieldString, oneof_serialize)
{
InSequence s;
string_or_bytes<10, 10> msg;
Mocks::WriteBufferMock buffer;
msg.mutable_txt() = "Foo bar";
EXPECT_CALL(buffer, get_available_size()).Times(1).WillOnce(Return(99));
uint8_t expected[] = {0x0a, 0x07};
for(auto e : expected)
{
EXPECT_CALL(buffer, push(e)).Times(1).WillOnce(Return(true));
}
EXPECT_CALL(buffer, push(_, 7)).Times(1).WillOnce(Return(true));
EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
EXPECT_EQ(10, msg.txt().get_max_length());
}
TEST(FieldString, oneof_deserialize)
{
InSequence s;
string_or_bytes<10, 10> msg;
Mocks::ReadBufferMock buffer;
uint8_t referee[] = {0x0a, 0x07, 0x46, 0x6f, 0x6f, 0x20, 0x62, 0x61, 0x72};
for(auto r: referee)
{
EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(r), Return(true)));
}
EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(Return(false));
EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.deserialize(buffer));
EXPECT_EQ(7, msg.txt().get_length());
EXPECT_STREQ(msg.get_txt(), "Foo bar");
}
TEST(FieldBytes, set_get)
{
raw_bytes<10> msg;
msg.mutable_b()[0] = 1;
EXPECT_EQ(1, msg.b().get_length());
EXPECT_EQ(1, msg.b().get_const(0));
msg.clear();
EXPECT_EQ(0, msg.b().get_length());
EXPECT_EQ(0, msg.b().get_const(0));
msg.mutable_b()[1] = 2;
EXPECT_EQ(2, msg.b().get_length());
EXPECT_EQ(0, msg.b().get_const(0));
EXPECT_EQ(2, msg.b().get_const(1));
// Check index out of bound will return the last element.
msg.mutable_b()[10] = 11; // max index should be 9.
// The last element should be changed
EXPECT_EQ(10, msg.b().get_length());
EXPECT_EQ(11, msg.b().get_const(9));
// Check this function out of bound aswell.
EXPECT_EQ(11, msg.b().get_const(10));
// Try to set more bytes compared to what will fit.
uint8_t big_array[11] = {0};
big_array[10] = 11;
EXPECT_EQ(::EmbeddedProto::Error::ARRAY_FULL, msg.mutable_b().set(big_array, 11));
}
TEST(FieldBytes, clear)
{
raw_bytes<10> msg;
const uint8_t array[2] = {1 ,2};
// Clear the field specific.
msg.mutable_b().set(array, 2);
EXPECT_EQ(2, msg.b().get_length());
msg.clear_b();
EXPECT_EQ(0, msg.b().get_length());
// Clear the whole message.
msg.mutable_b().set(array, 2);
msg.clear();
EXPECT_EQ(0, msg.b().get_length());
}
TEST(FieldBytes, serialize)
{
InSequence s;
raw_bytes<10> msg;
Mocks::WriteBufferMock buffer;
uint8_t bytes[] = {1u, 2u, 3u, 0u};
msg.mutable_b().set(bytes, 4);
EXPECT_CALL(buffer, get_available_size()).Times(1).WillOnce(Return(17));
uint8_t expected[] = {0x0a, 0x04};
for(auto e : expected)
{
EXPECT_CALL(buffer, push(e)).Times(1).WillOnce(Return(true));
}
EXPECT_CALL(buffer, push(_, 4)).Times(1).WillOnce(Return(true));
EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
EXPECT_EQ(10, msg.b().get_max_length());
}
TEST(FieldBytes, deserialize)
{
InSequence s;
raw_bytes<10> msg;
Mocks::ReadBufferMock buffer;
uint8_t referee[] = {0x0a, 0x04, 0x01, 0x02, 0x03, 0x00};
for(auto r: referee)
{
EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(r), Return(true)));
}
EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(Return(false));
EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.deserialize(buffer));
EXPECT_EQ(4, msg.b().get_length());
EXPECT_EQ(1, msg.b()[0]);
EXPECT_EQ(2, msg.b()[1]);
EXPECT_EQ(3, msg.b()[2]);
EXPECT_EQ(0, msg.b()[3]);
}
TEST(FieldBytes, deserialize_error_invalid_wiretype)
{
InSequence s;
raw_bytes<10> msg;
Mocks::ReadBufferMock buffer;
// The first byte is an invalid wiretype
EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(0x09), Return(true)));
EXPECT_EQ(::EmbeddedProto::Error::INVALID_WIRETYPE, msg.deserialize(buffer));
EXPECT_EQ(0, msg.b().get_length());
}
TEST(FieldBytes, oneof_set_get)
{
string_or_bytes<10, 10> msg;
msg.mutable_txt() = "Foo Bar";
auto id = string_or_bytes<10, 10>::id::TXT;
EXPECT_EQ(id, msg.get_which_s_or_b());
EXPECT_STREQ(msg.get_txt(), "Foo Bar");
// Switch to the array
uint8_t array[] = {1, 2, 3, 4, 5};
msg.mutable_b().set(array, 5);
id = string_or_bytes<10, 10>::id::B;
EXPECT_EQ(id, msg.get_which_s_or_b());
for(uint8_t i = 0; i < 5; ++i)
{
EXPECT_EQ(i+1, msg.get_b()[i]);
}
}
TEST(FieldBytes, oneof_clear)
{
raw_bytes<10> msg;
const uint8_t array[2] = {1 ,2};
// Clear the field specific.
msg.mutable_b().set(array, 2);
EXPECT_EQ(2, msg.b().get_length());
msg.clear_b();
EXPECT_EQ(0, msg.b().get_length());
// Clear the whole message.
msg.mutable_b().set(array, 2);
msg.clear();
EXPECT_EQ(0, msg.b().get_length());
}
TEST(FieldBytes, oneof_serialize)
{
InSequence s;
string_or_bytes<10, 10> msg;
Mocks::WriteBufferMock buffer;
uint8_t bytes[] = {1u, 2u, 3u, 0u};
msg.mutable_b().set(bytes, 4);
EXPECT_CALL(buffer, get_available_size()).Times(1).WillOnce(Return(17));
uint8_t expected[] = {0x12, 0x04};
for(auto e : expected)
{
EXPECT_CALL(buffer, push(e)).Times(1).WillOnce(Return(true));
}
EXPECT_CALL(buffer, push(_, 4)).Times(1).WillOnce(Return(true));
EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
EXPECT_EQ(10, msg.txt().get_max_length());
}
TEST(FieldBytes, oneof_deserialize)
{
InSequence s;
string_or_bytes<10, 10> msg;
Mocks::ReadBufferMock buffer;
uint8_t referee[] = {0x12, 0x04, 0x01, 0x02, 0x03, 0x00};
for(auto r: referee)
{
EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(r), Return(true)));
}
EXPECT_CALL(buffer, pop(_)).Times(1).WillOnce(Return(false));
EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.deserialize(buffer));
EXPECT_EQ(4, msg.b().get_length());
EXPECT_EQ(1, msg.b()[0]);
EXPECT_EQ(2, msg.b()[1]);
EXPECT_EQ(3, msg.b()[2]);
EXPECT_EQ(0, msg.b()[3]);
}
TEST(RepeatedStringBytes, empty)
{
repeated_string_bytes<3, 10, 3, 10> msg;
Mocks::WriteBufferMock buffer;
EXPECT_CALL(buffer, get_available_size()).Times(2).WillRepeatedly(Return(99));
EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
}
TEST(RepeatedStringBytes, get_set)
{
repeated_string_bytes<3, 15, 3, 15> msg;
::EmbeddedProto::FieldString<15> str;
msg.add_array_of_txt(str);
msg.mutable_array_of_txt(0) = "Foo bar 1";
msg.add_array_of_txt(str);
msg.mutable_array_of_txt(1) = "Foo bar 2";
str = "Foo bar 3";
msg.add_array_of_txt(str);
EXPECT_EQ(3, msg.array_of_txt().get_length());
EXPECT_EQ(0, msg.array_of_bytes().get_length());
EXPECT_STREQ(msg.array_of_txt(0).get_const(), "Foo bar 1");
EXPECT_STREQ(msg.array_of_txt(1).get_const(), "Foo bar 2");
EXPECT_STREQ(msg.array_of_txt(2).get_const(), "Foo bar 3");
}
TEST(RepeatedStringBytes, serialize)
{
InSequence s;
repeated_string_bytes<3, 15, 3, 15> msg;
Mocks::WriteBufferMock buffer;
::EmbeddedProto::FieldString<15> str;
msg.add_array_of_txt(str);
msg.mutable_array_of_txt(0) = "Foo bar 1";
msg.add_array_of_txt(str);
msg.mutable_array_of_txt(1) = "";
msg.add_array_of_txt(str);
msg.mutable_array_of_txt(2) = "Foo bar 3";
// We need 24 bytes to serialze the strings above.
EXPECT_CALL(buffer, get_available_size()).Times(1).WillOnce(Return(24));
// The first string.
// Id and size of array of txt.
EXPECT_CALL(buffer, push(0x0a)).Times(1).WillOnce(Return(true));
EXPECT_CALL(buffer, push(0x09)).Times(1).WillOnce(Return(true));
// The string is pushed as an array, we do not know the pointer value so use _, but we do know
// the size.
EXPECT_CALL(buffer, push(_, 9)).Times(1).WillOnce(Return(true));
// The empty string
EXPECT_CALL(buffer, push(0x0a)).Times(1).WillOnce(Return(true));
EXPECT_CALL(buffer, push(0x00)).Times(1).WillOnce(Return(true));
// The last string
EXPECT_CALL(buffer, push(0x0a)).Times(1).WillOnce(Return(true));
EXPECT_CALL(buffer, push(0x09)).Times(1).WillOnce(Return(true));
EXPECT_CALL(buffer, push(_, 9)).Times(1).WillOnce(Return(true));
EXPECT_CALL(buffer, get_available_size()).Times(1).WillOnce(Return(0));
EXPECT_EQ(::EmbeddedProto::Error::NO_ERRORS, msg.serialize(buffer));
}
} // End of namespace test_EmbeddedAMS_string_bytes