From 2fdb5f90c358e7c64980e34c78183636b19cd825 Mon Sep 17 00:00:00 2001
From: Yash Tibrewal <yashkt@google.com>
Date: Thu, 17 Feb 2022 15:24:56 -0800
Subject: [PATCH] CompositeChannelCredentials: Comparator implementation
 (#28902)

---
 .../composite/composite_credentials.h         |  7 +--
 test/core/security/credentials_test.cc        | 49 +++++++++++++++++++
 2 files changed, 53 insertions(+), 3 deletions(-)

diff --git a/src/core/lib/security/credentials/composite/composite_credentials.h b/src/core/lib/security/credentials/composite/composite_credentials.h
index fe2da4bd0ac..1d7a387ec4a 100644
--- a/src/core/lib/security/credentials/composite/composite_credentials.h
+++ b/src/core/lib/security/credentials/composite/composite_credentials.h
@@ -64,9 +64,10 @@ class grpc_composite_channel_credentials : public grpc_channel_credentials {
 
  private:
   int cmp_impl(const grpc_channel_credentials* other) const override {
-    // TODO(yashykt): Check if we can do something better here
-    return grpc_core::QsortCompare(
-        static_cast<const grpc_channel_credentials*>(this), other);
+    auto* o = static_cast<const grpc_composite_channel_credentials*>(other);
+    int r = inner_creds_->cmp(o->inner_creds_.get());
+    if (r != 0) return r;
+    return call_creds_->cmp(o->call_creds_.get());
   }
 
   grpc_core::RefCountedPtr<grpc_channel_credentials> inner_creds_;
diff --git a/test/core/security/credentials_test.cc b/test/core/security/credentials_test.cc
index 1c7d2945dfd..8faf98604ae 100644
--- a/test/core/security/credentials_test.cc
+++ b/test/core/security/credentials_test.cc
@@ -3598,6 +3598,55 @@ TEST(CredentialsTest, TestFakeCallCredentialsCompareFailure) {
   grpc_call_credentials_release(md_creds);
 }
 
+TEST(CredentialsTest, TestCompositeChannelCredsCompareSuccess) {
+  auto* insecure_creds = grpc_insecure_credentials_create();
+  auto* fake_channel_creds = grpc_fake_transport_security_credentials_create();
+  auto fake_creds = grpc_core::MakeRefCounted<fake_call_creds>();
+  auto* composite_creds_1 = grpc_composite_channel_credentials_create(
+      insecure_creds, fake_creds.get(), nullptr);
+  auto* composite_creds_2 = grpc_composite_channel_credentials_create(
+      fake_channel_creds, fake_creds.get(), nullptr);
+  EXPECT_NE(composite_creds_1->cmp(composite_creds_2), 0);
+  EXPECT_NE(composite_creds_2->cmp(composite_creds_1), 0);
+  grpc_channel_credentials_release(insecure_creds);
+  grpc_channel_credentials_release(composite_creds_1);
+  grpc_channel_credentials_release(composite_creds_2);
+}
+
+TEST(CredentialsTest,
+     TestCompositeChannelCredsCompareFailureDifferentChannelCreds) {
+  auto* insecure_creds = grpc_insecure_credentials_create();
+  auto fake_creds = grpc_core::MakeRefCounted<fake_call_creds>();
+  auto* md_creds = grpc_md_only_test_credentials_create("key", "value", false);
+  auto* composite_creds_1 = grpc_composite_channel_credentials_create(
+      insecure_creds, fake_creds.get(), nullptr);
+  auto* composite_creds_2 = grpc_composite_channel_credentials_create(
+      insecure_creds, md_creds, nullptr);
+  EXPECT_NE(composite_creds_1->cmp(composite_creds_2), 0);
+  EXPECT_NE(composite_creds_2->cmp(composite_creds_1), 0);
+  grpc_channel_credentials_release(insecure_creds);
+  grpc_call_credentials_release(md_creds);
+  grpc_channel_credentials_release(composite_creds_1);
+  grpc_channel_credentials_release(composite_creds_2);
+}
+
+TEST(CredentialsTest,
+     TestCompositeChannelCredsCompareFailureDifferentCallCreds) {
+  auto* insecure_creds = grpc_insecure_credentials_create();
+  auto fake_creds = grpc_core::MakeRefCounted<fake_call_creds>();
+  auto* md_creds = grpc_md_only_test_credentials_create("key", "value", false);
+  auto* composite_creds_1 = grpc_composite_channel_credentials_create(
+      insecure_creds, fake_creds.get(), nullptr);
+  auto* composite_creds_2 = grpc_composite_channel_credentials_create(
+      insecure_creds, md_creds, nullptr);
+  EXPECT_NE(composite_creds_1->cmp(composite_creds_2), 0);
+  EXPECT_NE(composite_creds_2->cmp(composite_creds_1), 0);
+  grpc_channel_credentials_release(insecure_creds);
+  grpc_call_credentials_release(md_creds);
+  grpc_channel_credentials_release(composite_creds_1);
+  grpc_channel_credentials_release(composite_creds_2);
+}
+
 TEST(CredentialsTest, TestXdsCredentialsCompareSucces) {
   auto* insecure_creds = grpc_insecure_credentials_create();
   auto* xds_creds_1 = grpc_xds_credentials_create(insecure_creds);