Add alias and option to support migration

The main goal of the change is to allow us to change the name of the
blobId while making sure the existing data is still valid during the
migration. Added an alias option which allow us to have two possible
valid blobId and will use the `baseBlobId` to commit the data even if
the current data match the alish ID. This allow us to change the blobId
of the binary store without loosing the data.

Also added an option to revert back to the alias blobId with the
`blobtool` to support backward compatibility when we need to downgrade
to a version without alias support. Created the base service that gets
trigger to start the blob id revert.

Tested:

Tested backward compatibility and working fine. The blob data are not
lost between versions.

Change-Id: I75bcbce3aff20c6ee8a491bef36fac260595d6f7
Signed-off-by: Willy Tu <wltu@google.com>
diff --git a/test/binarystore_unittest.cpp b/test/binarystore_unittest.cpp
index 5d82f81..5b618e3 100644
--- a/test/binarystore_unittest.cpp
+++ b/test/binarystore_unittest.cpp
@@ -9,6 +9,7 @@
 #include <iterator>
 #include <memory>
 #include <sstream>
+#include <stdplus/print.hpp>
 #include <vector>
 
 #include <gmock/gmock.h>
@@ -119,6 +120,20 @@
     EXPECT_EQ(initialData, blobDataStorage);
 }
 
+TEST_F(BinaryStoreTest, SimpleLoadWithAlias)
+{
+    auto testDataFile = createBlobStorage(inputProto);
+    auto initialData = blobDataStorage;
+    auto store = binstore::BinaryStore::createFromConfig(
+        "/blob/my-test-2", std::move(testDataFile), std::nullopt,
+        "/blob/my-test");
+    EXPECT_THAT(store->getBlobIds(),
+                UnorderedElementsAre("/blob/my-test-2", "/blob/my-test-2/0",
+                                     "/blob/my-test-2/1", "/blob/my-test-2/2",
+                                     "/blob/my-test-2/3"));
+    EXPECT_NE(initialData, blobDataStorage);
+}
+
 TEST_F(BinaryStoreTest, TestCreateFromFile)
 {
     auto testDataFile = createBlobStorage(inputProto);
@@ -135,6 +150,24 @@
     EXPECT_EQ(initialData, blobDataStorage);
 }
 
+TEST_F(BinaryStoreTest, TestSetBaseBlobId)
+{
+    auto testDataFile = createBlobStorage(inputProto);
+    auto initialData = blobDataStorage;
+    auto store = binstore::BinaryStore::createFromConfig(
+        "/blob/my-test", std::move(testDataFile), std::nullopt);
+    ASSERT_TRUE(store);
+    EXPECT_EQ("/blob/my-test", store->getBaseBlobId());
+    EXPECT_TRUE(store->setBaseBlobId("/blob/my-test-1"));
+    EXPECT_EQ("/blob/my-test-1", store->getBaseBlobId());
+    EXPECT_THAT(store->getBlobIds(),
+                UnorderedElementsAre("/blob/my-test-1", "/blob/my-test-1/0",
+                                     "/blob/my-test-1/1", "/blob/my-test-1/2",
+                                     "/blob/my-test-1/3"));
+    // Check that the storage has changed
+    EXPECT_NE(initialData, blobDataStorage);
+}
+
 TEST_F(BinaryStoreTest, TestReadBlob)
 {
     auto testDataFile = createBlobStorage(inputProto);
diff --git a/test/meson.build b/test/meson.build
index 66a964c..fe4c0f2 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -6,6 +6,7 @@
   dependencies: [gtest, gmock])
 
 tests = [
+  'binarystore_unittest',
   'parse_config_unittest',
   'sys_file_unittest',
   'handler_unittest',
diff --git a/test/parse_config_unittest.cpp b/test/parse_config_unittest.cpp
index 772dcc8..b0f1ac2 100644
--- a/test/parse_config_unittest.cpp
+++ b/test/parse_config_unittest.cpp
@@ -26,7 +26,9 @@
       "blobBaseId": "/test/",
       "sysFilePath": "/sys/fake/path",
       "offsetBytes": 32,
-      "maxSizeBytes": 2
+      "maxSizeBytes": 2,
+      "aliasBlobBaseId": "/test2/",
+      "migrateToAlias": true
     }
   )"_json;
 
@@ -37,6 +39,8 @@
     EXPECT_EQ(config.sysFilePath, "/sys/fake/path");
     EXPECT_EQ(config.offsetBytes, 32);
     EXPECT_EQ(config.maxSizeBytes, 2);
+    EXPECT_EQ(config.aliasBlobBaseId, "/test2/");
+    EXPECT_TRUE(config.migrateToAlias);
 }
 
 TEST(ParseConfigTest, TestConfigArray)