typecd: Implement partner discovery complete check

Implement the DiscoveryComplete() Partner method which checks whether
all the available alternate modes have been registered. Also update the
unit test to check for this.

BUG=b:152251292
TEST=Unit tests still pass.

Change-Id: If44fabaf1b505a9e1ac94560262bc59dc2004bcd
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2601497
Reviewed-by: Mengqi Guo <mqg@chromium.org>
Reviewed-by: Prashant Malani <pmalani@chromium.org>
Commit-Queue: Prashant Malani <pmalani@chromium.org>
Tested-by: Prashant Malani <pmalani@chromium.org>
diff --git a/typecd/partner.cc b/typecd/partner.cc
index 00c2d1a..84d2f2b 100644
--- a/typecd/partner.cc
+++ b/typecd/partner.cc
@@ -116,4 +116,8 @@
   return alt_modes_.find(index)->second.get();
 }
 
+bool Partner::DiscoveryComplete() {
+  return num_alt_modes_ == alt_modes_.size();
+}
+
 }  // namespace typecd
diff --git a/typecd/partner.h b/typecd/partner.h
index 415dc0a..1d13826 100644
--- a/typecd/partner.h
+++ b/typecd/partner.h
@@ -57,6 +57,12 @@
   // doesn't exist.
   AltMode* GetAltMode(int index);
 
+  // Checks whether partner PD discovery is complete (and we have all the PD
+  // information that the kernel can provide). To determine this, we check
+  // whether the number of registered altmodes equals the |num_alt_modes_| value
+  // which is read from sysfs.
+  bool DiscoveryComplete();
+
  private:
   // A map representing all the alternate modes supported by the partner.
   // The key is the index of the alternate mode as determined by the connector
diff --git a/typecd/partner_test.cc b/typecd/partner_test.cc
index 6c5eead..fc88287 100644
--- a/typecd/partner_test.cc
+++ b/typecd/partner_test.cc
@@ -38,22 +38,40 @@
   base::ScopedTempDir scoped_temp_dir_;
 };
 
-// Check that calls of AddAltMode() done explicitly function correctly. Also
-// check that trying to Add the same alt mode twice fails.
+// Check that calls of AddAltMode() which are done explicitly function
+// correctly. Also check that trying to add the same alt mode twice fails. While
+// we are here, also check that calls to DiscoveryComplete return the right
+// responses at various times of the discovery process.
 TEST_F(PartnerTest, TestAltModeManualAddition) {
-  Partner p((base::FilePath(kFakePort0PartnerSysPath)));
+  auto partner_path = temp_dir_.Append(std::string("port0-partner"));
+  ASSERT_TRUE(base::CreateDirectory(partner_path));
+
+  Partner p(partner_path);
 
   // Set up fake sysfs paths.
+
+  // Add the sysfs entry and run the update code (in production, this
+  // will run in response to a udev event, but since we don't have that here,
+  // call it manually).
+  std::string num_altmodes("2");
+  ASSERT_TRUE(base::WriteFile(partner_path.Append("number_of_alternate_modes"),
+                              num_altmodes.c_str(), num_altmodes.length()));
+  p.UpdatePDInfoFromSysfs();
+
+  // Add the 1st alt mode sysfs directory.
   std::string mode0_dirname =
       base::StringPrintf("port%d-partner.%d", 0, kDPAltModeIndex);
-  auto mode0_path = temp_dir_.Append(mode0_dirname);
+  auto mode0_path = partner_path.Append(mode0_dirname);
   ASSERT_TRUE(CreateFakeAltMode(mode0_path, kDPSVID, kDPVDO, kDPVDOIndex));
-
   EXPECT_TRUE(p.AddAltMode(mode0_path));
 
+  // We still have 1 more alt mode to register.
+  EXPECT_FALSE(p.DiscoveryComplete());
+
+  // Add the 2nd alt mode sysfs directory.
   std::string mode1_dirname =
       base::StringPrintf("port%d-partner.%d", 0, kTBTAltModeIndex);
-  auto mode1_path = temp_dir_.Append(mode1_dirname);
+  auto mode1_path = partner_path.Append(mode1_dirname);
   ASSERT_TRUE(CreateFakeAltMode(mode1_path, kTBTSVID, kTBTVDO, kTBTVDOIndex));
 
   // Add extra white spaces to ensure malformed strings can be parsed. We can do
@@ -61,8 +79,11 @@
   auto mode1_svid = base::StringPrintf("%x    ", kTBTSVID);
   ASSERT_TRUE(base::WriteFile(mode1_path.Append("svid"), mode1_svid.c_str(),
                               mode1_svid.length()));
-
   EXPECT_TRUE(p.AddAltMode(mode1_path));
+
+  // Discovery can now be considered complete.
+  EXPECT_TRUE(p.DiscoveryComplete());
+
   // Trying to add an existing alt mode again should fail.
   EXPECT_FALSE(p.AddAltMode(mode1_path));
 }
diff --git a/typecd/port.cc b/typecd/port.cc
index 9459a41..c07f3c7 100644
--- a/typecd/port.cc
+++ b/typecd/port.cc
@@ -274,9 +274,13 @@
 }
 
 bool Port::IsPartnerDiscoveryComplete() {
-  // TODO(b/152251292) needs to be implemented.
-  NOTIMPLEMENTED();
-  return true;
+  if (!partner_) {
+    LOG(INFO)
+        << "Trying to check discovery complete for a non-existent partner.";
+    return false;
+  }
+
+  return partner_->DiscoveryComplete();
 }
 
 bool Port::IsCableAltModePresent(uint16_t altmode_sid) {