<commit_before>#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include <string.h>

#include <RingBuffer.h>
#include <AsyncComm.h>

using ::testing::Return;
using ::testing::ReturnArg;
using ::testing::Sequence;
using ::testing::_;
using ::testing::WithArgs;
using ::testing::Invoke;

class MockSerial {
public:

	MOCK_METHOD0(read, int());
	MOCK_METHOD0(available, int());
	MOCK_METHOD2(write, size_t(const void*, size_t));

	MockSerial() {
		ON_CALL(*this, available()).WillByDefault(Return(0));
		ON_CALL(*this, write(_, _)).WillByDefault(ReturnArg<1>());
	}
};

template <uint16_t BUFFER_SIZE>
struct MockCallBacks: public AsyncCommCallBacks<BUFFER_SIZE> {
	typedef StringBuffer<BUFFER_SIZE> Buffer;

	MOCK_METHOD1_T(clbk_executing, bool(Buffer&));
	MOCK_METHOD1_T(clbk_timeout, void(Buffer&));
	MOCK_METHOD1_T(clbk_buffer_overflow, void(Buffer&));
	MOCK_METHOD1_T(clbk_event, void(Buffer&));

	MockCallBacks() {
		ON_CALL(*this, clbk_executing(_)).WillByDefault(Return(true));
	}
};

class AsyncCommTest: public testing::Test {
public:
	size_t fakeSerialDataIn(std::string str) {
		Sequence s;
		for (size_t i = 0; i < str.size(); ++i) {
			EXPECT_CALL(serial, available()).InSequence(s).WillOnce(
					Return(str.length() - i));
			EXPECT_CALL(serial, read()).InSequence(s).WillOnce(Return(str[i]));
		}
		EXPECT_CALL(serial, available()).InSequence(s).WillRepeatedly(
				Return(0));
		return str.length();
	}

  MockSerial serial;
  MockCallBacks<64> callbacks;
};

template<typename T>
::testing::AssertionResult ArraysMatch(const T* expected, const T* actual,
		size_t len) {
	for (size_t i = 0; i < len; ++i) {
		if (expected[i] != actual[i]) {
			return ::testing::AssertionFailure() << "array[" << i << "] ("
					<< actual[i] << ") != expected[" << i << "] ("
					<< expected[i] << ")";
		}
	}
	return ::testing::AssertionSuccess();
}

TEST_F(AsyncCommTest, one_tick_no_data) {
	AsyncComm<MockSerial, decltype(callbacks)> comm(serial, callbacks);
	EXPECT_CALL(serial, available());
	comm.tick();
}

TEST_F(AsyncCommTest, one_tick_timeout) {
  AsyncComm<MockSerial, decltype(callbacks)> comm(serial, callbacks);

  EXPECT_CALL(serial, write(_, _));
  ASSERT_TRUE(comm.exec("", 0));
  const unsigned long timeout = ASYNC_COMM_TIMEOUT_MS + 10;
  unsigned long start = millis();
  bool has_timeout = false;

  EXPECT_CALL(callbacks, clbk_executing(_)).WillRepeatedly(Return(true));
  EXPECT_CALL(callbacks, clbk_timeout(_)).WillOnce(Invoke([&has_timeout](decltype(callbacks)::Buffer&) {
	has_timeout = true;
      }));
  EXPECT_CALL(serial, available()).WillRepeatedly(Return(0));
  
  while(millis() - start < timeout) {
    comm.tick();
  }
  ASSERT_TRUE(has_timeout);
}

TEST_F(AsyncCommTest, one_tick_buffer_overflow) {
  AsyncComm<MockSerial, decltype(callbacks)> comm(serial, callbacks);

  std::string str;
  bool has_overflow = false;
  str.resize(decltype(callbacks)::Buffer::capacity());
  fakeSerialDataIn(str);
  EXPECT_CALL(callbacks, clbk_event(_));
  EXPECT_CALL(callbacks, clbk_buffer_overflow(_)).WillOnce(Invoke([&has_overflow](decltype(callbacks)::Buffer&) {
	has_overflow = true;
      }));
  comm.tick();
  ASSERT_TRUE(has_overflow);
}

TEST_F(AsyncCommTest, one_tick_event) {
	AsyncComm<MockSerial, decltype(callbacks)> comm(serial, callbacks);

	size_t len = fakeSerialDataIn("1234");
	EXPECT_CALL(callbacks, clbk_event(_)).WillOnce(
			WithArgs<0>(
					Invoke(
							[&](decltype(callbacks)::Buffer &buff) {
								ASSERT_EQ(len, buff.length());
								ASSERT_TRUE(ArraysMatch("1234", reinterpret_cast<const char*>(buff.buffer()), len));
							})));
	comm.tick();
	EXPECT_CALL(callbacks, clbk_event(_)).WillOnce(
			WithArgs<0>(
					Invoke(
							[&](decltype(callbacks)::Buffer &buff) {
								ASSERT_EQ(len, buff.length());
								ASSERT_TRUE(ArraysMatch("1234", reinterpret_cast<const char*>(buff.buffer()), len));
							})));
	EXPECT_CALL(serial, write("", 0));
	ASSERT_TRUE(comm.exec("", 0));
}

TEST_F(AsyncCommTest, exec_tick) {
	AsyncComm<MockSerial, decltype(callbacks)> comm(serial, callbacks);
	std::string cmd("AT\r\n");
	EXPECT_CALL(serial, write(_, cmd.length()));
	// send command
	ASSERT_TRUE(comm.exec(cmd.c_str(), cmd.length()));
	// expect to fail because first command has not completed nor timeout
	ASSERT_FALSE(comm.exec("", 0));

	size_t len = fakeSerialDataIn("OK");
	EXPECT_CALL(callbacks, clbk_executing(_));
	comm.tick();
	len += fakeSerialDataIn("\r\n");
	EXPECT_CALL(callbacks, clbk_executing(_)).WillOnce(
			DoAll(WithArgs<0>(Invoke([&](decltype(callbacks)::Buffer &buff) {
				ASSERT_EQ(len, buff.length());
				ASSERT_EQ(buff.index_of("OK\r\n"), 0);
				ASSERT_EQ(buff.pop_firsts(len), len);
			})), Return(false)));<commit_msg>rename mock to avoid conflict between tests set. (could use namespaces)<commit_after>#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include <string.h>

#include <RingBuffer.h>
#include <AsyncComm.h>

using ::testing::Return;
using ::testing::ReturnArg;
using ::testing::Sequence;
using ::testing::_;
using ::testing::WithArgs;
using ::testing::Invoke;

class AsyncMockSerial {
public:

	MOCK_METHOD0(read, int());
	MOCK_METHOD0(available, int());
	MOCK_METHOD2(write, size_t(const void*, size_t));

	AsyncMockSerial() {
		ON_CALL(*this, available()).WillByDefault(Return(0));
		ON_CALL(*this, write(_, _)).WillByDefault(ReturnArg<1>());
	}
};

template <uint16_t BUFFER_SIZE>
struct AsyncMockCallBacks: public AsyncCommCallBacks<BUFFER_SIZE> {
	typedef StringBuffer<BUFFER_SIZE> Buffer;

	MOCK_METHOD1_T(clbk_executing, bool(Buffer&));
	MOCK_METHOD1_T(clbk_timeout, void(Buffer&));
	MOCK_METHOD1_T(clbk_buffer_overflow, void(Buffer&));
	MOCK_METHOD1_T(clbk_event, void(Buffer&));

	AsyncMockCallBacks() {
		ON_CALL(*this, clbk_executing(_)).WillByDefault(Return(true));
	}
};

class AsyncCommTest: public testing::Test {
public:
	size_t fakeSerialDataIn(std::string str) {
		Sequence s;
		for (size_t i = 0; i < str.size(); ++i) {
			EXPECT_CALL(serial, available()).InSequence(s).WillOnce(
					Return(str.length() - i));
			EXPECT_CALL(serial, read()).InSequence(s).WillOnce(Return(str[i]));
		}
		EXPECT_CALL(serial, available()).InSequence(s).WillRepeatedly(
				Return(0));
		return str.length();
	}

	AsyncMockSerial serial;
	AsyncMockCallBacks<64> callbacks;
};

template<typename T>
::testing::AssertionResult ArraysMatch(const T* expected, const T* actual,
		size_t len) {
	for (size_t i = 0; i < len; ++i) {
		if (expected[i] != actual[i]) {
			return ::testing::AssertionFailure() << "array[" << i << "] ("
					<< actual[i] << ") != expected[" << i << "] ("
					<< expected[i] << ")";
		}
	}
	return ::testing::AssertionSuccess();
}

TEST_F(AsyncCommTest, one_tick_no_data) {
	AsyncComm<AsyncMockSerial, decltype(callbacks)> comm(serial, callbacks);
	EXPECT_CALL(serial, available());
	comm.tick();
}

TEST_F(AsyncCommTest, one_tick_timeout) {
  AsyncComm<AsyncMockSerial, decltype(callbacks)> comm(serial, callbacks);

  EXPECT_CALL(serial, write(_, _));
  ASSERT_TRUE(comm.exec("", 0));
  const unsigned long timeout = ASYNC_COMM_TIMEOUT_MS + 10;
  unsigned long start = millis();
  bool has_timeout = false;

  EXPECT_CALL(callbacks, clbk_executing(_)).WillRepeatedly(Return(true));
  EXPECT_CALL(callbacks, clbk_timeout(_)).WillOnce(Invoke([&has_timeout](decltype(callbacks)::Buffer&) {
	has_timeout = true;
      }));
  EXPECT_CALL(serial, available()).WillRepeatedly(Return(0));
  
  while(millis() - start < timeout) {
    comm.tick();
  }
  ASSERT_TRUE(has_timeout);
}

TEST_F(AsyncCommTest, one_tick_buffer_overflow) {
  AsyncComm<AsyncMockSerial, decltype(callbacks)> comm(serial, callbacks);

  std::string str;
  bool has_overflow = false;
  str.resize(decltype(callbacks)::Buffer::capacity());
  fakeSerialDataIn(str);
  EXPECT_CALL(callbacks, clbk_event(_));
  EXPECT_CALL(callbacks, clbk_buffer_overflow(_)).WillOnce(Invoke([&has_overflow](decltype(callbacks)::Buffer&) {
	has_overflow = true;
      }));
  comm.tick();
  ASSERT_TRUE(has_overflow);
}

TEST_F(AsyncCommTest, one_tick_event) {
	AsyncComm<AsyncMockSerial, decltype(callbacks)> comm(serial, callbacks);

	size_t len = fakeSerialDataIn("1234");
	EXPECT_CALL(callbacks, clbk_event(_)).WillOnce(
			WithArgs<0>(
					Invoke(
							[&](decltype(callbacks)::Buffer &buff) {
								ASSERT_EQ(len, buff.length());
								ASSERT_TRUE(ArraysMatch("1234", reinterpret_cast<const char*>(buff.buffer()), len));
							})));
	comm.tick();
	EXPECT_CALL(callbacks, clbk_event(_)).WillOnce(
			WithArgs<0>(
					Invoke(
							[&](decltype(callbacks)::Buffer &buff) {
								ASSERT_EQ(len, buff.length());
								ASSERT_TRUE(ArraysMatch("1234", reinterpret_cast<const char*>(buff.buffer()), len));
							})));
	EXPECT_CALL(serial, write("", 0));
	ASSERT_TRUE(comm.exec("", 0));
}

TEST_F(AsyncCommTest, exec_tick) {
	AsyncComm<AsyncMockSerial, decltype(callbacks)> comm(serial, callbacks);
	std::string cmd("AT\r\n");
	EXPECT_CALL(serial, write(_, cmd.length()));
	// send command
	ASSERT_TRUE(comm.exec(cmd.c_str(), cmd.length()));
	// expect to fail because first command has not completed nor timeout
	ASSERT_FALSE(comm.exec("", 0));

	size_t len = fakeSerialDataIn("OK");
	EXPECT_CALL(callbacks, clbk_executing(_));
	comm.tick();
	len += fakeSerialDataIn("\r\n");
	EXPECT_CALL(callbacks, clbk_executing(_)).WillOnce(
			DoAll(WithArgs<0>(Invoke([&](decltype(callbacks)::Buffer &buff) {
				ASSERT_EQ(len, buff.length());
				ASSERT_EQ(buff.index_of("OK\r\n"), 0);
				ASSERT_EQ(buff.pop_firsts(len), len);
			})), Return(false)));
{'fraction_non_alphanumeric': 0.17224729715545292, 'fraction_numerical': 0.008187257268814948, 'mean_word_length': 5.944606413994169, 'pattern_counts': {'":': 0, '<': 87, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '780566', 'n_tokens_mistral': 3638, 'n_tokens_neox': 3371, 'n_words': 559}