psutils: Move functions from updater to utils

Move common, utility functions from updater.*pp to utils.*pp.  This will
enable those functions to be used by other command line options in the
psutils tool.

Modify --get-version and --get-model to use the new utility functions.

Also update --get-version to provide a single getVersion() function that
handles the existence of the psu.json file as a low-level implementation
detail.

Tested:
* Verified all automated tests run successfully
* Verified --get-version still works
  * With psu.json file
  * Without psu.json file
* Verified --get-model still works
  * With psu.json file
  * Without psu.json file
* Verified --update still gets correct device path, device name, and I2C
  bus/address from functions that moved to utils.*pp
* The complete test plan is available at
  https://gist.github.com/smccarney/c049e24655d32e22cab9d521d145774a

Change-Id: I51ceca10957dc9a924d0d7516dc29632a6ed82d3
Signed-off-by: Shawn McCarney <shawnmm@us.ibm.com>
diff --git a/tools/power-utils/test/meson.build b/tools/power-utils/test/meson.build
index 61c5f53..33d3df1 100644
--- a/tools/power-utils/test/meson.build
+++ b/tools/power-utils/test/meson.build
@@ -1,33 +1,13 @@
 test(
-    'test_version',
+    'psutils-tests',
     executable(
-        'test_version',
-        'test_version.cpp',
-        '../version.cpp',
-        '../utils.cpp',
-        dependencies: [
-            gtest,
-            nlohmann_json_dep,
-            phosphor_logging,
-        ],
-        implicit_include_directories: false,
-        include_directories: libpower_inc,
-        link_args: dynamic_linker,
-        build_rpath: get_option('oe-sdk').allowed() ? rpath : '',
-        link_with: [
-            libpower,
-        ],
-        objects: record_manager,
-    )
-)
-
-test(
-    'test_updater',
-    executable(
-        'test_updater',
+        'psutils-tests',
         'test_updater.cpp',
+        'test_utils.cpp',
+        'test_version.cpp',
         '../updater.cpp',
         '../utils.cpp',
+        '../version.cpp',
         dependencies: [
             gtest,
             gmock,
@@ -46,6 +26,5 @@
             libpower,
             libi2c_dev_mock
         ],
-        objects: record_manager,
     )
 )
diff --git a/tools/power-utils/test/test_updater.cpp b/tools/power-utils/test/test_updater.cpp
index 9c34926..a56d2df 100644
--- a/tools/power-utils/test/test_updater.cpp
+++ b/tools/power-utils/test/test_updater.cpp
@@ -27,17 +27,6 @@
 using ::testing::An;
 using ::testing::Pointee;
 
-namespace updater
-{
-namespace internal
-{
-
-std::string getDeviceName(std::string devPath);
-std::pair<uint8_t, uint8_t> parseDeviceName(const std::string& devName);
-
-} // namespace internal
-} // namespace updater
-
 using namespace updater;
 
 class TestUpdater : public ::testing::Test
@@ -103,30 +92,3 @@
     EXPECT_CALL(i2c, read(0xf1, An<uint8_t&>()));
     updater->doUpdate();
 }
-
-TEST_F(TestUpdater, getDeviceName)
-{
-    auto ret = internal::getDeviceName("");
-    EXPECT_TRUE(ret.empty());
-
-    ret = internal::getDeviceName("/sys/bus/i2c/devices/3-0069");
-    EXPECT_EQ("3-0069", ret);
-
-    ret = internal::getDeviceName("/sys/bus/i2c/devices/3-0069/");
-    EXPECT_EQ("3-0069", ret);
-}
-
-TEST_F(TestUpdater, parseDeviceName)
-{
-    auto [id, addr] = internal::parseDeviceName("3-0068");
-    EXPECT_EQ(3, id);
-    EXPECT_EQ(0x68, addr);
-
-    std::tie(id, addr) = internal::parseDeviceName("11-0069");
-    EXPECT_EQ(11, id);
-    EXPECT_EQ(0x69, addr);
-
-    EXPECT_THROW(internal::parseDeviceName("no-number"), std::invalid_argument);
-
-    EXPECT_DEATH(internal::parseDeviceName("invalid"), "");
-}
diff --git a/tools/power-utils/test/test_utils.cpp b/tools/power-utils/test/test_utils.cpp
new file mode 100644
index 0000000..b88d024
--- /dev/null
+++ b/tools/power-utils/test/test_utils.cpp
@@ -0,0 +1,50 @@
+/**
+ * Copyright © 2024 IBM Corporation
+ *
+ * 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 "../utils.hpp"
+
+#include <stdexcept>
+#include <tuple>
+
+#include <gtest/gtest.h>
+
+using namespace utils;
+
+TEST(TestUtils, getDeviceName)
+{
+    auto ret = getDeviceName("");
+    EXPECT_TRUE(ret.empty());
+
+    ret = getDeviceName("/sys/bus/i2c/devices/3-0069");
+    EXPECT_EQ("3-0069", ret);
+
+    ret = getDeviceName("/sys/bus/i2c/devices/3-0069/");
+    EXPECT_EQ("3-0069", ret);
+}
+
+TEST(TestUtils, parseDeviceName)
+{
+    auto [id, addr] = parseDeviceName("3-0068");
+    EXPECT_EQ(3, id);
+    EXPECT_EQ(0x68, addr);
+
+    std::tie(id, addr) = parseDeviceName("11-0069");
+    EXPECT_EQ(11, id);
+    EXPECT_EQ(0x69, addr);
+
+    EXPECT_THROW(parseDeviceName("no-number"), std::invalid_argument);
+
+    EXPECT_DEATH(parseDeviceName("invalid"), "");
+}