external_storer: Add a log entry limit

This is to ensure that we don't get uncapped log entries. Default is set
to the first 20 logs being saved, and the next 980 being in a circualr
queue (1000 entries in total).

Tested:
Added unit test to ensure that the queue works as intended. Also
verified by injecting 1000 entries to ensure that the buffer indeed
saves the first 20, and caps it 1000.

```
//LogEntry1:
Created: ...Entries/66a97808-1e22-4c1e-b0f6-4b9eb7c714e7/index.json
...
//LogEntry20:
Created: ...Entries/9c07937a-9524-40f1-acef-19db73b46678/index.json
//LogEntry21:
Created: ...Entries/0bfb7ede-8020-4613-bfcf-5815ca176c79/index.json
...
//LogEntry1001:
Removed: ...Entries/0bfb7ede-8020-4613-bfcf-5815ca176c79
Created: ...Entries/31bdf3be-1e87-4e77-922d-9bbac09ac824/index.json
```

We can see that starting on the 1001st log, log entry 21 is deleted to
make room.

Signed-off-by: Brandon Kim <brandonkim@google.com>
Change-Id: Ic2badd7f01741d788cad829c9e203b7c4962fc8e
diff --git a/test/external_storer_file_test.cpp b/test/external_storer_file_test.cpp
index 3cba35d..c0f2578 100644
--- a/test/external_storer_file_test.cpp
+++ b/test/external_storer_file_test.cpp
@@ -15,6 +15,7 @@
 
 using ::testing::_;
 using ::testing::DoAll;
+using ::testing::InSequence;
 using ::testing::Return;
 using ::testing::SaveArg;
 
@@ -26,6 +27,7 @@
     MOCK_METHOD(bool, createFile,
                 (const std::string& path, const nlohmann::json& jsonPdr),
                 (const, override));
+    MOCK_METHOD(bool, removeAll, (const std::string& path), (const, override));
 };
 
 class ExternalStorerFileTest : public ::testing::Test
@@ -36,8 +38,9 @@
         mockFileWriter(std::make_unique<MockFileWriter>())
     {
         mockFileWriterPtr = dynamic_cast<MockFileWriter*>(mockFileWriter.get());
+        // Set the queue of LogEntry to 1 saved entry and 2 non saved entry
         exStorer = std::make_unique<ExternalStorerFileInterface>(
-            conn, rootPath, std::move(mockFileWriter));
+            conn, rootPath, std::move(mockFileWriter), 1, 2);
     }
 
   protected:
@@ -127,6 +130,7 @@
 
 TEST_F(ExternalStorerFileTest, LogEntryTest)
 {
+    InSequence s;
     // Before sending a LogEntry, first we need to push a LogService.
     std::string jsonLogSerivce = R"(
       {
@@ -146,19 +150,62 @@
         .WillOnce(Return(true));
     EXPECT_THAT(exStorer->publishJson(jsonLogSerivce), true);
 
-    // Now send a LogEntry
+    // Now send a LogEntry#1, which will not be deleted
     std::string jsonLogEntry = R"(
       {
         "@odata.id": "/some/odata/id",
         "@odata.type": "#LogEntry.v1_13_0.LogEntry"
       }
     )";
-
     nlohmann::json logEntryOut;
+    std::string logPath1;
     EXPECT_CALL(*mockFileWriterPtr, createFile(_, _))
-        .WillOnce(DoAll(SaveArg<1>(&logEntryOut), Return(true)));
-
+        .WillOnce(DoAll(SaveArg<0>(&logPath1), SaveArg<1>(&logEntryOut),
+                        Return(true)));
     EXPECT_THAT(exStorer->publishJson(jsonLogEntry), true);
+    EXPECT_FALSE(logPath1.empty());
+    EXPECT_NE(logEntryOut["Id"], nullptr);
+    EXPECT_EQ(logEntryOut["@odata.id"], nullptr);
+
+    // Now send a LogEntry#2, which will be the first to be deleted
+    std::string logPath2;
+    EXPECT_CALL(*mockFileWriterPtr, createFile(_, _))
+        .WillOnce(DoAll(SaveArg<0>(&logPath2), SaveArg<1>(&logEntryOut),
+                        Return(true)));
+    EXPECT_THAT(exStorer->publishJson(jsonLogEntry), true);
+    EXPECT_FALSE(logPath2.empty());
+    EXPECT_NE(logEntryOut["Id"], nullptr);
+    EXPECT_EQ(logEntryOut["@odata.id"], nullptr);
+
+    // Now send a LogEntry#3
+    std::string logPath3;
+    EXPECT_CALL(*mockFileWriterPtr, createFile(_, _))
+        .WillOnce(DoAll(SaveArg<0>(&logPath3), SaveArg<1>(&logEntryOut),
+                        Return(true)));
+    EXPECT_THAT(exStorer->publishJson(jsonLogEntry), true);
+    EXPECT_FALSE(logPath3.empty());
+    EXPECT_NE(logEntryOut["Id"], nullptr);
+    EXPECT_EQ(logEntryOut["@odata.id"], nullptr);
+
+    // Now send a LogEntry#4, we expect the LogEntry#2 to be deleted
+    std::string logPath4;
+    EXPECT_CALL(*mockFileWriterPtr, removeAll(logPath2)).WillOnce(Return(true));
+    EXPECT_CALL(*mockFileWriterPtr, createFile(_, _))
+        .WillOnce(DoAll(SaveArg<0>(&logPath4), SaveArg<1>(&logEntryOut),
+                        Return(true)));
+    EXPECT_THAT(exStorer->publishJson(jsonLogEntry), true);
+    EXPECT_FALSE(logPath4.empty());
+    EXPECT_NE(logEntryOut["Id"], nullptr);
+    EXPECT_EQ(logEntryOut["@odata.id"], nullptr);
+
+    // Now send a LogEntry#5, we expect the LogEntry#3 to be deleted
+    std::string logPath5;
+    EXPECT_CALL(*mockFileWriterPtr, removeAll(logPath3)).WillOnce(Return(true));
+    EXPECT_CALL(*mockFileWriterPtr, createFile(_, _))
+        .WillOnce(DoAll(SaveArg<0>(&logPath5), SaveArg<1>(&logEntryOut),
+                        Return(true)));
+    EXPECT_THAT(exStorer->publishJson(jsonLogEntry), true);
+    EXPECT_FALSE(logPath5.empty());
     EXPECT_NE(logEntryOut["Id"], nullptr);
     EXPECT_EQ(logEntryOut["@odata.id"], nullptr);
 }