version: getBMCVersion: Support value without quotes

Yocto upstream has removed the quotes from the VERSION_ID value
in os-release[1].
Update getBMCVersion() to support unquoted values.

[1]: http://git.yoctoproject.org/cgit/cgit.cgi/poky/commit/?id=4d98363d59cd422b6357148bc0862256ca2076cb

Closes openbmc/phosphor-bmc-code-mgmt#4

Tested: Added unit test cases and verified on a witherspoon with
        and without quotes.

Change-Id: I904a90a611e43722955fb31b1a4b673b1e6e725f
Signed-off-by: Adriana Kobylak <anoo@us.ibm.com>
diff --git a/test/utest.cpp b/test/utest.cpp
index 361367e..0d8e306 100644
--- a/test/utest.cpp
+++ b/test/utest.cpp
@@ -74,6 +74,36 @@
     EXPECT_EQ(Version::getValue(manifestFilePath, "purpose"), purpose);
 }
 
+TEST_F(VersionTest, TestGetVersionWithQuotes)
+{
+    auto releasePath = _directory + "/" + "os-release";
+    auto version = "1.2.3-test-version";
+
+    std::ofstream file;
+    file.open(releasePath, std::ofstream::out);
+    ASSERT_TRUE(file.is_open());
+
+    file << "VERSION_ID=\"" << version << "\"\n";
+    file.close();
+
+    EXPECT_EQ(Version::getBMCVersion(releasePath), version);
+}
+
+TEST_F(VersionTest, TestGetVersionWithoutQuotes)
+{
+    auto releasePath = _directory + "/" + "os-release";
+    auto version = "9.88.1-test-version";
+
+    std::ofstream file;
+    file.open(releasePath, std::ofstream::out);
+    ASSERT_TRUE(file.is_open());
+
+    file << "VERSION_ID=" << version << "\n";
+    file.close();
+
+    EXPECT_EQ(Version::getBMCVersion(releasePath), version);
+}
+
 /** @brief Make sure we correctly get the Id from getId()*/
 TEST_F(VersionTest, TestGetId)
 {
diff --git a/version.cpp b/version.cpp
index 91f478b..f50500a 100644
--- a/version.cpp
+++ b/version.cpp
@@ -129,6 +129,7 @@
 std::string Version::getBMCVersion(const std::string& releaseFilePath)
 {
     std::string versionKey = "VERSION_ID=";
+    std::string versionValue{};
     std::string version{};
     std::ifstream efile;
     std::string line;
@@ -139,8 +140,24 @@
         if (line.substr(0, versionKey.size()).find(versionKey) !=
             std::string::npos)
         {
-            std::size_t pos = line.find_first_of('"') + 1;
-            version = line.substr(pos, line.find_last_of('"') - pos);
+            // Support quoted and unquoted values
+            // 1. Remove the versionKey so that we process the value only.
+            versionValue = line.substr(versionKey.size());
+
+            // 2. Look for a starting quote, then increment the position by 1 to
+            //    skip the quote character. If no quote is found,
+            //    find_first_of() returns npos (-1), which by adding +1 sets pos
+            //    to 0 (beginning of unquoted string).
+            std::size_t pos = versionValue.find_first_of('"') + 1;
+
+            // 3. Look for ending quote, then decrease the position by pos to
+            //    get the size of the string up to before the ending quote. If
+            //    no quote is found, find_last_of() returns npos (-1), and pos
+            //    is 0 for the unquoted case, so substr() is called with a len
+            //    parameter of npos (-1) which according to the documentation
+            //    indicates to use all characters until the end of the string.
+            version =
+                versionValue.substr(pos, versionValue.find_last_of('"') - pos);
             break;
         }
     }