lshal: Add tests for ListCommand::parseArgs

Test: lshal_test
Bug: 35389839
Change-Id: Iaef39b048b0e7c06e70e21c96448c2f2e24d3128
diff --git a/cmds/lshal/ListCommand.h b/cmds/lshal/ListCommand.h
index 51f1ca5..64d33ca 100644
--- a/cmds/lshal/ListCommand.h
+++ b/cmds/lshal/ListCommand.h
@@ -40,7 +40,7 @@
 public:
     ListCommand(Lshal &lshal);
     Status main(const std::string &command, const Arg &arg);
-private:
+protected:
     Status parseArgs(const std::string &command, const Arg &arg);
     Status fetch();
     void postprocess();
diff --git a/cmds/lshal/Lshal.h b/cmds/lshal/Lshal.h
index 00db5d0..d3cc4e2 100644
--- a/cmds/lshal/Lshal.h
+++ b/cmds/lshal/Lshal.h
@@ -33,13 +33,14 @@
 class Lshal {
 public:
     Lshal();
+    virtual ~Lshal() {}
     Lshal(std::ostream &out, std::ostream &err,
             sp<hidl::manager::V1_0::IServiceManager> serviceManager,
             sp<hidl::manager::V1_0::IServiceManager> passthroughManager);
     Status main(const Arg &arg);
     void usage(const std::string &command = "") const;
-    NullableOStream<std::ostream> err() const;
-    NullableOStream<std::ostream> out() const;
+    virtual NullableOStream<std::ostream> err() const;
+    virtual NullableOStream<std::ostream> out() const;
     const sp<hidl::manager::V1_0::IServiceManager> &serviceManager() const;
     const sp<hidl::manager::V1_0::IServiceManager> &passthroughManager() const;
 
diff --git a/cmds/lshal/test.cpp b/cmds/lshal/test.cpp
index b9ed538..6cdec29 100644
--- a/cmds/lshal/test.cpp
+++ b/cmds/lshal/test.cpp
@@ -27,6 +27,7 @@
 #include <android/hardware/tests/baz/1.0/IQuux.h>
 #include <hidl/HidlTransportSupport.h>
 
+#include "ListCommand.h"
 #include "Lshal.h"
 
 #define NELEMS(array)   static_cast<int>(sizeof(array) / sizeof(array[0]))
@@ -166,6 +167,72 @@
     EXPECT_THAT(err.str(), HasSubstr("does not exist"));
 }
 
+class MockLshal : public Lshal {
+public:
+    MockLshal() {}
+    ~MockLshal() = default;
+    MOCK_CONST_METHOD0(out, NullableOStream<std::ostream>());
+    MOCK_CONST_METHOD0(err, NullableOStream<std::ostream>());
+};
+
+// expose protected fields and methods for ListCommand
+class MockListCommand : public ListCommand {
+public:
+    MockListCommand(Lshal* lshal) : ListCommand(*lshal) {}
+
+    Status parseArgs(const Arg& arg) { return ListCommand::parseArgs("", arg); }
+    void forEachTable(const std::function<void(const Table &)> &f) const {
+        return ListCommand::forEachTable(f);
+    }
+};
+
+class ListParseArgsTest : public ::testing::Test {
+public:
+    void SetUp() override {
+        mockLshal = std::make_unique<NiceMock<MockLshal>>();
+        mockList = std::make_unique<MockListCommand>(mockLshal.get());
+        // ListCommand::parseArgs should parse arguments from the second element
+        optind = 1;
+    }
+    std::unique_ptr<MockLshal> mockLshal;
+    std::unique_ptr<MockListCommand> mockList;
+    std::stringstream output;
+};
+
+TEST_F(ListParseArgsTest, Default) {
+    // default args
+    EXPECT_EQ(0u, mockList->parseArgs(createArg({})));
+    mockList->forEachTable([](const Table& table) {
+        EXPECT_EQ(SelectedColumns({TableColumnType::INTERFACE_NAME, TableColumnType::THREADS,
+                                   TableColumnType::SERVER_PID, TableColumnType::CLIENT_PIDS}),
+                  table.getSelectedColumns());
+    });
+}
+
+TEST_F(ListParseArgsTest, Args) {
+    EXPECT_EQ(0u, mockList->parseArgs(createArg({"lshal", "-p", "-i", "-a", "-c"})));
+    mockList->forEachTable([](const Table& table) {
+        EXPECT_EQ(SelectedColumns({TableColumnType::SERVER_PID, TableColumnType::INTERFACE_NAME,
+                                   TableColumnType::SERVER_ADDR, TableColumnType::CLIENT_PIDS}),
+                  table.getSelectedColumns());
+    });
+}
+
+TEST_F(ListParseArgsTest, Cmds) {
+    EXPECT_EQ(0u, mockList->parseArgs(createArg({"lshal", "-m"})));
+    mockList->forEachTable([](const Table& table) {
+        EXPECT_EQ(SelectedColumns({TableColumnType::INTERFACE_NAME, TableColumnType::THREADS,
+                                   TableColumnType::SERVER_CMD, TableColumnType::CLIENT_CMDS}),
+                  table.getSelectedColumns());
+    });
+}
+
+TEST_F(ListParseArgsTest, DebugAndNeat) {
+    ON_CALL(*mockLshal, err()).WillByDefault(Return(NullableOStream<std::ostream>(output)));
+    EXPECT_NE(0u, mockList->parseArgs(createArg({"lshal", "--neat", "-d"})));
+    EXPECT_THAT(output.str(), StrNe(""));
+}
+
 } // namespace lshal
 } // namespace android