Implement discovery commands

This commit does the following
- Implements the GetPLDMTypes and GetPLDMCommands commands. These are
  commands that need to be handled by a PLDM device as part of the
  initial PLDM discovery.
- Sets up the build infrastructure: separate libraries for PLDM
  encode/decode libs and the PLDM responder.

Change-Id: I65fa222d2a681c473f579c8e30d84faaf94fe754
Signed-off-by: Deepak Kodihalli <dkodihal@in.ibm.com>
diff --git a/test/Makefile.am b/test/Makefile.am
new file mode 100644
index 0000000..82101f7
--- /dev/null
+++ b/test/Makefile.am
@@ -0,0 +1,35 @@
+AM_CPPFLAGS = -I$(top_srcdir)
+
+TESTS = $(check_PROGRAMS)
+
+check_PROGRAMS = \
+	libpldm_base_test \
+	libpldmresponder_base_test
+
+test_cppflags = \
+	-Igtest \
+	$(GTEST_CPPFLAGS) \
+	$(AM_CPPFLAGS)
+
+test_cxxflags = \
+	$(PTHREAD_CFLAGS)
+
+test_ldflags = \
+	-lgtest_main \
+	-lgtest \
+	$(PTHREAD_LIBS) \
+	$(OESDK_TESTCASE_FLAGS)
+
+libpldm_base_test_CPPFLAGS = $(test_cppflags)
+libpldm_base_test_CXXFLAGS = $(test_cxxflags)
+libpldm_base_test_LDFLAGS = $(test_ldflags)
+libpldm_base_test_LDADD = $(top_builddir)/libpldm/base.o
+libpldm_base_test_SOURCES = libpldm_base_test.cpp
+
+libpldmresponder_base_test_CPPFLAGS = $(test_cppflags)
+libpldmresponder_base_test_CXXFLAGS = $(test_cxxflags)
+libpldmresponder_base_test_LDFLAGS = $(test_ldflags)
+libpldmresponder_base_test_LDADD = \
+	$(top_builddir)/libpldm/base.o \
+	$(top_builddir)/libpldmresponder/base.o
+libpldmresponder_base_test_SOURCES = libpldmresponder_base_test.cpp
diff --git a/test/libpldm_base_test.cpp b/test/libpldm_base_test.cpp
new file mode 100644
index 0000000..3be7ddd
--- /dev/null
+++ b/test/libpldm_base_test.cpp
@@ -0,0 +1,121 @@
+#include <string.h>
+
+#include <array>
+
+#include "libpldm/base.h"
+
+#include <gtest/gtest.h>
+
+TEST(GetPLDMCommands, testEncodeRequest)
+{
+    uint8_t pldmType = 0x05;
+    pldm_version version{0xFF, 0xFF, 0xFF, 0xFF};
+    std::array<uint8_t, PLDM_GET_COMMANDS_REQ_BYTES> requestMsg{};
+    pldm_msg request{};
+    request.body.payload = requestMsg.data();
+    request.body.payload_length = requestMsg.size();
+
+    auto rc = encode_get_commands_req(0, pldmType, version, &request);
+    ASSERT_EQ(rc, PLDM_SUCCESS);
+    ASSERT_EQ(0, memcmp(request.body.payload, &pldmType, sizeof(pldmType)));
+    ASSERT_EQ(0, memcmp(request.body.payload + sizeof(pldmType), &version,
+                        sizeof(version)));
+}
+
+TEST(GetPLDMCommands, testDecodeRequest)
+{
+    uint8_t pldmType = 0x05;
+    pldm_version version{0xFF, 0xFF, 0xFF, 0xFF};
+    uint8_t pldmTypeOut{};
+    pldm_version versionOut{0xFF, 0xFF, 0xFF, 0xFF};
+    std::array<uint8_t, PLDM_GET_COMMANDS_REQ_BYTES> requestMsg{};
+    pldm_msg_payload request{};
+    request.payload = requestMsg.data();
+    request.payload_length = requestMsg.size();
+
+    memcpy(request.payload, &pldmType, sizeof(pldmType));
+    memcpy(request.payload + sizeof(pldmType), &version, sizeof(version));
+    auto rc = decode_get_commands_req(&request, &pldmTypeOut, &versionOut);
+    ASSERT_EQ(rc, PLDM_SUCCESS);
+    ASSERT_EQ(pldmTypeOut, pldmType);
+    ASSERT_EQ(0, memcmp(&versionOut, &version, sizeof(version)));
+}
+
+TEST(GetPLDMCommands, testEncodeResponse)
+{
+    uint8_t completionCode = 0;
+    std::array<uint8_t, PLDM_GET_COMMANDS_RESP_BYTES> responseMsg{};
+    pldm_msg response{};
+    response.body.payload = responseMsg.data();
+    response.body.payload_length = responseMsg.size();
+    std::array<uint8_t, PLDM_MAX_CMDS_PER_TYPE / 8> commands{};
+    commands[0] = 1;
+    commands[1] = 2;
+    commands[2] = 3;
+
+    auto rc =
+        encode_get_commands_resp(0, PLDM_SUCCESS, commands.data(), &response);
+    ASSERT_EQ(rc, PLDM_SUCCESS);
+    ASSERT_EQ(completionCode, response.body.payload[0]);
+    ASSERT_EQ(1, response.body.payload[1]);
+    ASSERT_EQ(2, response.body.payload[2]);
+    ASSERT_EQ(3, response.body.payload[3]);
+}
+
+TEST(GetPLDMTypes, testEncodeResponse)
+{
+    uint8_t completionCode = 0;
+    std::array<uint8_t, PLDM_GET_TYPES_RESP_BYTES> responseMsg{};
+    pldm_msg response{};
+    response.body.payload = responseMsg.data();
+    response.body.payload_length = responseMsg.size();
+    std::array<uint8_t, PLDM_MAX_TYPES / 8> types{};
+    types[0] = 1;
+    types[1] = 2;
+    types[2] = 3;
+
+    auto rc = encode_get_types_resp(0, PLDM_SUCCESS, types.data(), &response);
+    ASSERT_EQ(rc, PLDM_SUCCESS);
+    ASSERT_EQ(completionCode, response.body.payload[0]);
+    ASSERT_EQ(1, response.body.payload[1]);
+    ASSERT_EQ(2, response.body.payload[2]);
+    ASSERT_EQ(3, response.body.payload[3]);
+}
+
+TEST(GetPLDMTypes, testDecodeResponse)
+{
+    std::array<uint8_t, PLDM_GET_TYPES_RESP_BYTES> responseMsg{};
+    pldm_msg_payload response{};
+    response.payload = responseMsg.data();
+    response.payload_length = responseMsg.size();
+    response.payload[1] = 1;
+    response.payload[2] = 2;
+    response.payload[3] = 3;
+    std::array<uint8_t, PLDM_MAX_TYPES / 8> outTypes{};
+
+    auto rc = decode_get_types_resp(&response, outTypes.data());
+
+    ASSERT_EQ(rc, PLDM_SUCCESS);
+    ASSERT_EQ(response.payload[1], outTypes[0]);
+    ASSERT_EQ(response.payload[2], outTypes[1]);
+    ASSERT_EQ(response.payload[3], outTypes[2]);
+}
+
+TEST(GetPLDMCommands, testDecodeResponse)
+{
+    std::array<uint8_t, PLDM_MAX_CMDS_PER_TYPE> responseMsg{};
+    pldm_msg_payload response{};
+    response.payload = responseMsg.data();
+    response.payload_length = responseMsg.size();
+    response.payload[1] = 1;
+    response.payload[2] = 2;
+    response.payload[3] = 3;
+    std::array<uint8_t, PLDM_MAX_CMDS_PER_TYPE / 8> outTypes{};
+
+    auto rc = decode_get_commands_resp(&response, outTypes.data());
+
+    ASSERT_EQ(rc, PLDM_SUCCESS);
+    ASSERT_EQ(response.payload[1], outTypes[0]);
+    ASSERT_EQ(response.payload[2], outTypes[1]);
+    ASSERT_EQ(response.payload[3], outTypes[2]);
+}
diff --git a/test/libpldmresponder_base_test.cpp b/test/libpldmresponder_base_test.cpp
new file mode 100644
index 0000000..2bd6ebd
--- /dev/null
+++ b/test/libpldmresponder_base_test.cpp
@@ -0,0 +1,59 @@
+#include "libpldmresponder/base.hpp"
+
+#include <string.h>
+
+#include <array>
+
+#include "libpldm/base.h"
+
+#include <gtest/gtest.h>
+
+using namespace pldm::responder;
+
+TEST(GetPLDMTypes, testGoodRequest)
+{
+    pldm_msg_payload request{};
+    pldm_msg response{};
+    std::array<uint8_t, PLDM_GET_TYPES_RESP_BYTES> responseMsg{};
+    response.body.payload = responseMsg.data();
+    response.body.payload_length = responseMsg.size();
+    getPLDMTypes(&request, &response);
+    // Only base type supported at the moment
+    ASSERT_EQ(response.body.payload[0], 0);
+    ASSERT_EQ(response.body.payload[1], 1);
+    ASSERT_EQ(response.body.payload[2], 0);
+}
+
+TEST(GetPLDMCommands, testGoodRequest)
+{
+    // Only base type supported at the moment, and commands -
+    // GetPLDMTypes, GetPLDMCommands
+    pldm_msg response{};
+    std::array<uint8_t, PLDM_GET_COMMANDS_RESP_BYTES> responseMsg{};
+    response.body.payload = responseMsg.data();
+    response.body.payload_length = responseMsg.size();
+    pldm_msg_payload request{};
+    std::array<uint8_t, 5> requestPayload{};
+    request.payload = requestPayload.data();
+    request.payload_length = requestPayload.size();
+    getPLDMCommands(&request, &response);
+    ASSERT_EQ(response.body.payload[0], 0);
+    ASSERT_EQ(response.body.payload[1], 48); // 48 = 0b110000
+    ASSERT_EQ(response.body.payload[2], 0);
+}
+
+TEST(GetPLDMCommands, testBadRequest)
+{
+    pldm_msg response{};
+    std::array<uint8_t, PLDM_GET_COMMANDS_RESP_BYTES> responseMsg{};
+    response.body.payload = responseMsg.data();
+    response.body.payload_length = responseMsg.size();
+    pldm_msg_payload request{};
+    std::array<uint8_t, 5> requestPayload{};
+
+    request.payload = requestPayload.data();
+    request.payload[0] = 0xFF;
+    request.payload_length = requestPayload.size();
+    getPLDMCommands(&request, &response);
+    ASSERT_EQ(response.body.payload[0], PLDM_ERROR_INVALID_PLDM_TYPE);
+}