From 95aba4dbfdb396cf7b196227363fb687ea64d96a Mon Sep 17 00:00:00 2001
From: Pankaj Garg <pgarg2@apple.com>
Date: Wed, 16 Jun 2021 13:58:36 -0700
Subject: [PATCH] add tests for SessionIDAllocator

---
 .../secure_channel/SessionIDAllocator.cpp     |   4 +-
 src/protocols/secure_channel/tests/BUILD.gn   |   1 +
 .../tests/TestSessionIDAllocator.cpp          | 148 ++++++++++++++++++
 3 files changed, 152 insertions(+), 1 deletion(-)
 create mode 100644 src/protocols/secure_channel/tests/TestSessionIDAllocator.cpp

diff --git a/src/protocols/secure_channel/SessionIDAllocator.cpp b/src/protocols/secure_channel/SessionIDAllocator.cpp
index f2a81c5d6c3cfc..ae097ce089664f 100644
--- a/src/protocols/secure_channel/SessionIDAllocator.cpp
+++ b/src/protocols/secure_channel/SessionIDAllocator.cpp
@@ -34,7 +34,7 @@ CHIP_ERROR SessionIDAllocator::Allocate(uint16_t & id)
 
 void SessionIDAllocator::Free(uint16_t id)
 {
-    if (mNextAvailable == id && mNextAvailable > 0)
+    if (mNextAvailable > 0 && (mNextAvailable - 1) == id)
     {
         mNextAvailable--;
     }
@@ -49,6 +49,8 @@ CHIP_ERROR SessionIDAllocator::Reserve(uint16_t id)
         mNextAvailable++;
     }
 
+    // TODO - Check if ID is already allocated in SessionIDAllocator::Reserve()
+
     return CHIP_NO_ERROR;
 }
 
diff --git a/src/protocols/secure_channel/tests/BUILD.gn b/src/protocols/secure_channel/tests/BUILD.gn
index 6bbcfb328b9def..a48aa9a65dacf1 100644
--- a/src/protocols/secure_channel/tests/BUILD.gn
+++ b/src/protocols/secure_channel/tests/BUILD.gn
@@ -12,6 +12,7 @@ chip_test_suite("tests") {
     "TestCASESession.cpp",
     "TestMessageCounterManager.cpp",
     "TestPASESession.cpp",
+    "TestSessionIDAllocator.cpp",
     "TestStatusReport.cpp",
   ]
 
diff --git a/src/protocols/secure_channel/tests/TestSessionIDAllocator.cpp b/src/protocols/secure_channel/tests/TestSessionIDAllocator.cpp
new file mode 100644
index 00000000000000..3d0cd14cb6f066
--- /dev/null
+++ b/src/protocols/secure_channel/tests/TestSessionIDAllocator.cpp
@@ -0,0 +1,148 @@
+/*
+ *
+ *    Copyright (c) 2021 Project CHIP Authors
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#include <protocols/secure_channel/SessionIDAllocator.h>
+#include <support/CHIPMem.h>
+#include <support/UnitTestRegistration.h>
+
+#include <nlunit-test.h>
+
+using namespace chip;
+
+void TestStatusReport_Allocate(nlTestSuite * inSuite, void * inContext)
+{
+    SessionIDAllocator allocator;
+
+    NL_TEST_ASSERT(inSuite, allocator.Peek() == 0);
+
+    uint16_t id;
+
+    for (uint16_t i = 0; i < 16; i++)
+    {
+        CHIP_ERROR err = allocator.Allocate(id);
+        NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
+        NL_TEST_ASSERT(inSuite, id == i);
+        NL_TEST_ASSERT(inSuite, allocator.Peek() == i + 1);
+    }
+}
+
+void TestStatusReport_Free(nlTestSuite * inSuite, void * inContext)
+{
+    SessionIDAllocator allocator;
+
+    NL_TEST_ASSERT(inSuite, allocator.Peek() == 0);
+
+    uint16_t id;
+
+    for (uint16_t i = 0; i < 16; i++)
+    {
+        CHIP_ERROR err = allocator.Allocate(id);
+        NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
+        NL_TEST_ASSERT(inSuite, id == i);
+        NL_TEST_ASSERT(inSuite, allocator.Peek() == i + 1);
+    }
+
+    // Free an intermediate ID
+    allocator.Free(10);
+    NL_TEST_ASSERT(inSuite, allocator.Peek() == 16);
+
+    // Free the last allocated ID
+    allocator.Free(15);
+    NL_TEST_ASSERT(inSuite, allocator.Peek() == 15);
+
+    // Free some random unallocated ID
+    allocator.Free(100);
+    NL_TEST_ASSERT(inSuite, allocator.Peek() == 15);
+}
+
+void TestStatusReport_Reserve(nlTestSuite * inSuite, void * inContext)
+{
+    SessionIDAllocator allocator;
+
+    uint16_t id;
+
+    for (uint16_t i = 0; i < 16; i++)
+    {
+        CHIP_ERROR err = allocator.Allocate(id);
+        NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
+        NL_TEST_ASSERT(inSuite, id == i);
+        NL_TEST_ASSERT(inSuite, allocator.Peek() == i + 1);
+    }
+
+    allocator.Reserve(100);
+    NL_TEST_ASSERT(inSuite, allocator.Peek() == 101);
+}
+
+// Test Suite
+
+/**
+ *  Test Suite that lists all the test functions.
+ */
+// clang-format off
+static const nlTest sTests[] =
+{
+    NL_TEST_DEF("SessionIDAllocator_Allocate", TestStatusReport_Allocate),
+    NL_TEST_DEF("SessionIDAllocator_Free", TestStatusReport_Free),
+    NL_TEST_DEF("SessionIDAllocator_Reserve", TestStatusReport_Reserve),
+
+    NL_TEST_SENTINEL()
+};
+// clang-format on
+
+/**
+ *  Set up the test suite.
+ */
+static int TestSetup(void * inContext)
+{
+    CHIP_ERROR error = chip::Platform::MemoryInit();
+    if (error != CHIP_NO_ERROR)
+        return FAILURE;
+    return SUCCESS;
+}
+
+/**
+ *  Tear down the test suite.
+ */
+static int TestTeardown(void * inContext)
+{
+    chip::Platform::MemoryShutdown();
+    return SUCCESS;
+}
+
+// clang-format off
+static nlTestSuite sSuite =
+{
+    "Test-CHIP-SessionIDAllocator",
+    &sTests[0],
+    TestSetup,
+    TestTeardown,
+};
+// clang-format on
+
+/**
+ *  Main
+ */
+int TestStatusReport()
+{
+    // Run test suit against one context
+    nlTestRunner(&sSuite, nullptr);
+
+    return (nlTestRunnerStats(&sSuite));
+}
+
+CHIP_REGISTER_TEST_SUITE(TestStatusReport)