summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/p2p/base/transport_description_factory_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/p2p/base/transport_description_factory_unittest.cc')
-rw-r--r--third_party/libwebrtc/p2p/base/transport_description_factory_unittest.cc406
1 files changed, 406 insertions, 0 deletions
diff --git a/third_party/libwebrtc/p2p/base/transport_description_factory_unittest.cc b/third_party/libwebrtc/p2p/base/transport_description_factory_unittest.cc
new file mode 100644
index 0000000000..0da5b7c294
--- /dev/null
+++ b/third_party/libwebrtc/p2p/base/transport_description_factory_unittest.cc
@@ -0,0 +1,406 @@
+/*
+ * Copyright 2012 The WebRTC Project Authors. All rights reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "p2p/base/transport_description_factory.h"
+
+#include <stddef.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "p2p/base/p2p_constants.h"
+#include "p2p/base/transport_description.h"
+#include "rtc_base/copy_on_write_buffer.h"
+#include "rtc_base/fake_ssl_identity.h"
+#include "rtc_base/ssl_certificate.h"
+#include "rtc_base/ssl_fingerprint.h"
+#include "rtc_base/ssl_identity.h"
+#include "test/gmock.h"
+#include "test/gtest.h"
+#include "test/scoped_key_value_config.h"
+
+using cricket::TransportDescription;
+using cricket::TransportDescriptionFactory;
+using cricket::TransportOptions;
+using ::testing::Contains;
+using ::testing::Not;
+
+class TransportDescriptionFactoryTest : public ::testing::Test {
+ public:
+ TransportDescriptionFactoryTest()
+ : ice_credentials_({}),
+ f1_(field_trials_),
+ f2_(field_trials_),
+ cert1_(rtc::RTCCertificate::Create(std::unique_ptr<rtc::SSLIdentity>(
+ new rtc::FakeSSLIdentity("User1")))),
+ cert2_(rtc::RTCCertificate::Create(std::unique_ptr<rtc::SSLIdentity>(
+ new rtc::FakeSSLIdentity("User2")))) {}
+
+ void CheckDesc(const TransportDescription* desc,
+ absl::string_view opt,
+ absl::string_view ice_ufrag,
+ absl::string_view ice_pwd,
+ absl::string_view dtls_alg) {
+ ASSERT_TRUE(desc != NULL);
+ EXPECT_EQ(!opt.empty(), desc->HasOption(opt));
+ if (ice_ufrag.empty() && ice_pwd.empty()) {
+ EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
+ desc->ice_ufrag.size());
+ EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
+ desc->ice_pwd.size());
+ } else {
+ EXPECT_EQ(ice_ufrag, desc->ice_ufrag);
+ EXPECT_EQ(ice_pwd, desc->ice_pwd);
+ }
+ if (dtls_alg.empty()) {
+ EXPECT_TRUE(desc->identity_fingerprint.get() == NULL);
+ } else {
+ ASSERT_TRUE(desc->identity_fingerprint.get() != NULL);
+ EXPECT_EQ(desc->identity_fingerprint->algorithm, dtls_alg);
+ EXPECT_GT(desc->identity_fingerprint->digest.size(), 0U);
+ }
+ }
+
+ // This test ice restart by doing two offer answer exchanges. On the second
+ // exchange ice is restarted. The test verifies that the ufrag and password
+ // in the offer and answer is changed.
+ // If `dtls` is true, the test verifies that the finger print is not changed.
+ void TestIceRestart(bool dtls) {
+ SetDtls(dtls);
+ cricket::TransportOptions options;
+ // The initial offer / answer exchange.
+ std::unique_ptr<TransportDescription> offer =
+ f1_.CreateOffer(options, NULL, &ice_credentials_);
+ std::unique_ptr<TransportDescription> answer =
+ f2_.CreateAnswer(offer.get(), options, true, NULL, &ice_credentials_);
+
+ // Create an updated offer where we restart ice.
+ options.ice_restart = true;
+ std::unique_ptr<TransportDescription> restart_offer =
+ f1_.CreateOffer(options, offer.get(), &ice_credentials_);
+
+ VerifyUfragAndPasswordChanged(dtls, offer.get(), restart_offer.get());
+
+ // Create a new answer. The transport ufrag and password is changed since
+ // |options.ice_restart == true|
+ std::unique_ptr<TransportDescription> restart_answer = f2_.CreateAnswer(
+ restart_offer.get(), options, true, answer.get(), &ice_credentials_);
+ ASSERT_TRUE(restart_answer.get() != NULL);
+
+ VerifyUfragAndPasswordChanged(dtls, answer.get(), restart_answer.get());
+ }
+
+ void VerifyUfragAndPasswordChanged(bool dtls,
+ const TransportDescription* org_desc,
+ const TransportDescription* restart_desc) {
+ EXPECT_NE(org_desc->ice_pwd, restart_desc->ice_pwd);
+ EXPECT_NE(org_desc->ice_ufrag, restart_desc->ice_ufrag);
+ EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
+ restart_desc->ice_ufrag.size());
+ EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
+ restart_desc->ice_pwd.size());
+ // If DTLS is enabled, make sure the finger print is unchanged.
+ if (dtls) {
+ EXPECT_FALSE(
+ org_desc->identity_fingerprint->GetRfc4572Fingerprint().empty());
+ EXPECT_EQ(org_desc->identity_fingerprint->GetRfc4572Fingerprint(),
+ restart_desc->identity_fingerprint->GetRfc4572Fingerprint());
+ }
+ }
+
+ void TestIceRenomination(bool dtls) {
+ SetDtls(dtls);
+
+ cricket::TransportOptions options;
+ // The initial offer / answer exchange.
+ std::unique_ptr<TransportDescription> offer =
+ f1_.CreateOffer(options, nullptr, &ice_credentials_);
+ ASSERT_TRUE(offer);
+ EXPECT_THAT(offer->transport_options, Not(Contains("renomination")));
+
+ std::unique_ptr<TransportDescription> answer = f2_.CreateAnswer(
+ offer.get(), options, true, nullptr, &ice_credentials_);
+ ASSERT_TRUE(answer);
+ EXPECT_THAT(answer->transport_options, Not(Contains("renomination")));
+
+ options.enable_ice_renomination = true;
+ std::unique_ptr<TransportDescription> renomination_offer =
+ f1_.CreateOffer(options, offer.get(), &ice_credentials_);
+ ASSERT_TRUE(renomination_offer);
+ EXPECT_THAT(renomination_offer->transport_options,
+ Contains("renomination"));
+
+ std::unique_ptr<TransportDescription> renomination_answer =
+ f2_.CreateAnswer(renomination_offer.get(), options, true, answer.get(),
+ &ice_credentials_);
+ ASSERT_TRUE(renomination_answer);
+ EXPECT_THAT(renomination_answer->transport_options,
+ Contains("renomination"));
+ }
+
+ protected:
+ void SetDtls(bool dtls) {
+ if (dtls) {
+ f1_.set_secure(cricket::SEC_ENABLED);
+ f2_.set_secure(cricket::SEC_ENABLED);
+ f1_.set_certificate(cert1_);
+ f2_.set_certificate(cert2_);
+ } else {
+ f1_.set_secure(cricket::SEC_DISABLED);
+ f2_.set_secure(cricket::SEC_DISABLED);
+ }
+ }
+
+ webrtc::test::ScopedKeyValueConfig field_trials_;
+ cricket::IceCredentialsIterator ice_credentials_;
+ TransportDescriptionFactory f1_;
+ TransportDescriptionFactory f2_;
+
+ rtc::scoped_refptr<rtc::RTCCertificate> cert1_;
+ rtc::scoped_refptr<rtc::RTCCertificate> cert2_;
+};
+
+TEST_F(TransportDescriptionFactoryTest, TestOfferDefault) {
+ std::unique_ptr<TransportDescription> desc =
+ f1_.CreateOffer(TransportOptions(), NULL, &ice_credentials_);
+ CheckDesc(desc.get(), "", "", "", "");
+}
+
+TEST_F(TransportDescriptionFactoryTest, TestOfferDtls) {
+ f1_.set_secure(cricket::SEC_ENABLED);
+ f1_.set_certificate(cert1_);
+ std::string digest_alg;
+ ASSERT_TRUE(
+ cert1_->GetSSLCertificate().GetSignatureDigestAlgorithm(&digest_alg));
+ std::unique_ptr<TransportDescription> desc =
+ f1_.CreateOffer(TransportOptions(), NULL, &ice_credentials_);
+ CheckDesc(desc.get(), "", "", "", digest_alg);
+ // Ensure it also works with SEC_REQUIRED.
+ f1_.set_secure(cricket::SEC_REQUIRED);
+ desc = f1_.CreateOffer(TransportOptions(), NULL, &ice_credentials_);
+ CheckDesc(desc.get(), "", "", "", digest_alg);
+}
+
+// Test generating an offer with DTLS fails with no identity.
+TEST_F(TransportDescriptionFactoryTest, TestOfferDtlsWithNoIdentity) {
+ f1_.set_secure(cricket::SEC_ENABLED);
+ std::unique_ptr<TransportDescription> desc =
+ f1_.CreateOffer(TransportOptions(), NULL, &ice_credentials_);
+ ASSERT_TRUE(desc.get() == NULL);
+}
+
+// Test updating an offer with DTLS to pick ICE.
+// The ICE credentials should stay the same in the new offer.
+TEST_F(TransportDescriptionFactoryTest, TestOfferDtlsReofferDtls) {
+ f1_.set_secure(cricket::SEC_ENABLED);
+ f1_.set_certificate(cert1_);
+ std::string digest_alg;
+ ASSERT_TRUE(
+ cert1_->GetSSLCertificate().GetSignatureDigestAlgorithm(&digest_alg));
+ std::unique_ptr<TransportDescription> old_desc =
+ f1_.CreateOffer(TransportOptions(), NULL, &ice_credentials_);
+ ASSERT_TRUE(old_desc.get() != NULL);
+ std::unique_ptr<TransportDescription> desc =
+ f1_.CreateOffer(TransportOptions(), old_desc.get(), &ice_credentials_);
+ CheckDesc(desc.get(), "", old_desc->ice_ufrag, old_desc->ice_pwd, digest_alg);
+}
+
+TEST_F(TransportDescriptionFactoryTest, TestAnswerDefault) {
+ std::unique_ptr<TransportDescription> offer =
+ f1_.CreateOffer(TransportOptions(), NULL, &ice_credentials_);
+ ASSERT_TRUE(offer.get() != NULL);
+ std::unique_ptr<TransportDescription> desc = f2_.CreateAnswer(
+ offer.get(), TransportOptions(), true, NULL, &ice_credentials_);
+ CheckDesc(desc.get(), "", "", "", "");
+ desc = f2_.CreateAnswer(offer.get(), TransportOptions(), true, NULL,
+ &ice_credentials_);
+ CheckDesc(desc.get(), "", "", "", "");
+}
+
+// Test that we can update an answer properly; ICE credentials shouldn't change.
+TEST_F(TransportDescriptionFactoryTest, TestReanswer) {
+ std::unique_ptr<TransportDescription> offer =
+ f1_.CreateOffer(TransportOptions(), NULL, &ice_credentials_);
+ ASSERT_TRUE(offer.get() != NULL);
+ std::unique_ptr<TransportDescription> old_desc = f2_.CreateAnswer(
+ offer.get(), TransportOptions(), true, NULL, &ice_credentials_);
+ ASSERT_TRUE(old_desc.get() != NULL);
+ std::unique_ptr<TransportDescription> desc = f2_.CreateAnswer(
+ offer.get(), TransportOptions(), true, old_desc.get(), &ice_credentials_);
+ ASSERT_TRUE(desc.get() != NULL);
+ CheckDesc(desc.get(), "", old_desc->ice_ufrag, old_desc->ice_pwd, "");
+}
+
+// Test that we handle answering an offer with DTLS with no DTLS.
+TEST_F(TransportDescriptionFactoryTest, TestAnswerDtlsToNoDtls) {
+ f1_.set_secure(cricket::SEC_ENABLED);
+ f1_.set_certificate(cert1_);
+ std::unique_ptr<TransportDescription> offer =
+ f1_.CreateOffer(TransportOptions(), NULL, &ice_credentials_);
+ ASSERT_TRUE(offer.get() != NULL);
+ std::unique_ptr<TransportDescription> desc = f2_.CreateAnswer(
+ offer.get(), TransportOptions(), true, NULL, &ice_credentials_);
+ CheckDesc(desc.get(), "", "", "", "");
+}
+
+// Test that we handle answering an offer without DTLS if we have DTLS enabled,
+// but fail if we require DTLS.
+TEST_F(TransportDescriptionFactoryTest, TestAnswerNoDtlsToDtls) {
+ f2_.set_secure(cricket::SEC_ENABLED);
+ f2_.set_certificate(cert2_);
+ std::unique_ptr<TransportDescription> offer =
+ f1_.CreateOffer(TransportOptions(), NULL, &ice_credentials_);
+ ASSERT_TRUE(offer.get() != NULL);
+ std::unique_ptr<TransportDescription> desc = f2_.CreateAnswer(
+ offer.get(), TransportOptions(), true, NULL, &ice_credentials_);
+ CheckDesc(desc.get(), "", "", "", "");
+ f2_.set_secure(cricket::SEC_REQUIRED);
+ desc = f2_.CreateAnswer(offer.get(), TransportOptions(), true, NULL,
+ &ice_credentials_);
+ ASSERT_TRUE(desc.get() == NULL);
+}
+
+// Test that we handle answering an DTLS offer with DTLS, both if we have
+// DTLS enabled and required.
+TEST_F(TransportDescriptionFactoryTest, TestAnswerDtlsToDtls) {
+ f1_.set_secure(cricket::SEC_ENABLED);
+ f1_.set_certificate(cert1_);
+
+ f2_.set_secure(cricket::SEC_ENABLED);
+ f2_.set_certificate(cert2_);
+ // f2_ produces the answer that is being checked in this test, so the
+ // answer must contain fingerprint lines with cert2_'s digest algorithm.
+ std::string digest_alg2;
+ ASSERT_TRUE(
+ cert2_->GetSSLCertificate().GetSignatureDigestAlgorithm(&digest_alg2));
+
+ std::unique_ptr<TransportDescription> offer =
+ f1_.CreateOffer(TransportOptions(), NULL, &ice_credentials_);
+ ASSERT_TRUE(offer.get() != NULL);
+ std::unique_ptr<TransportDescription> desc = f2_.CreateAnswer(
+ offer.get(), TransportOptions(), true, NULL, &ice_credentials_);
+ CheckDesc(desc.get(), "", "", "", digest_alg2);
+ f2_.set_secure(cricket::SEC_REQUIRED);
+ desc = f2_.CreateAnswer(offer.get(), TransportOptions(), true, NULL,
+ &ice_credentials_);
+ CheckDesc(desc.get(), "", "", "", digest_alg2);
+}
+
+// Test that ice ufrag and password is changed in an updated offer and answer
+// if `TransportDescriptionOptions::ice_restart` is true.
+TEST_F(TransportDescriptionFactoryTest, TestIceRestart) {
+ TestIceRestart(false);
+}
+
+// Test that ice ufrag and password is changed in an updated offer and answer
+// if `TransportDescriptionOptions::ice_restart` is true and DTLS is enabled.
+TEST_F(TransportDescriptionFactoryTest, TestIceRestartWithDtls) {
+ TestIceRestart(true);
+}
+
+// Test that ice renomination is set in an updated offer and answer
+// if `TransportDescriptionOptions::enable_ice_renomination` is true.
+TEST_F(TransportDescriptionFactoryTest, TestIceRenomination) {
+ TestIceRenomination(false);
+}
+
+// Test that ice renomination is set in an updated offer and answer
+// if `TransportDescriptionOptions::enable_ice_renomination` is true and DTLS
+// is enabled.
+TEST_F(TransportDescriptionFactoryTest, TestIceRenominationWithDtls) {
+ TestIceRenomination(true);
+}
+
+// Test that offers and answers have ice-option:trickle.
+TEST_F(TransportDescriptionFactoryTest, AddsTrickleIceOption) {
+ cricket::TransportOptions options;
+ std::unique_ptr<TransportDescription> offer =
+ f1_.CreateOffer(options, nullptr, &ice_credentials_);
+ EXPECT_TRUE(offer->HasOption("trickle"));
+ std::unique_ptr<TransportDescription> answer =
+ f2_.CreateAnswer(offer.get(), options, true, nullptr, &ice_credentials_);
+ EXPECT_TRUE(answer->HasOption("trickle"));
+}
+
+// Test CreateOffer with IceCredentialsIterator.
+TEST_F(TransportDescriptionFactoryTest, CreateOfferIceCredentialsIterator) {
+ std::vector<cricket::IceParameters> credentials = {
+ cricket::IceParameters("kalle", "anka", false)};
+ cricket::IceCredentialsIterator credentialsIterator(credentials);
+ cricket::TransportOptions options;
+ std::unique_ptr<TransportDescription> offer =
+ f1_.CreateOffer(options, nullptr, &credentialsIterator);
+ EXPECT_EQ(offer->GetIceParameters().ufrag, credentials[0].ufrag);
+ EXPECT_EQ(offer->GetIceParameters().pwd, credentials[0].pwd);
+}
+
+// Test CreateAnswer with IceCredentialsIterator.
+TEST_F(TransportDescriptionFactoryTest, CreateAnswerIceCredentialsIterator) {
+ cricket::TransportOptions options;
+ std::unique_ptr<TransportDescription> offer =
+ f1_.CreateOffer(options, nullptr, &ice_credentials_);
+
+ std::vector<cricket::IceParameters> credentials = {
+ cricket::IceParameters("kalle", "anka", false)};
+ cricket::IceCredentialsIterator credentialsIterator(credentials);
+ std::unique_ptr<TransportDescription> answer = f1_.CreateAnswer(
+ offer.get(), options, false, nullptr, &credentialsIterator);
+ EXPECT_EQ(answer->GetIceParameters().ufrag, credentials[0].ufrag);
+ EXPECT_EQ(answer->GetIceParameters().pwd, credentials[0].pwd);
+}
+
+TEST_F(TransportDescriptionFactoryTest, CreateAnswerToDtlsActpassOffer) {
+ f1_.set_secure(cricket::SEC_ENABLED);
+ f1_.set_certificate(cert1_);
+
+ f2_.set_secure(cricket::SEC_ENABLED);
+ f2_.set_certificate(cert2_);
+ cricket::TransportOptions options;
+ std::unique_ptr<TransportDescription> offer =
+ f1_.CreateOffer(options, nullptr, &ice_credentials_);
+
+ std::unique_ptr<TransportDescription> answer =
+ f2_.CreateAnswer(offer.get(), options, false, nullptr, &ice_credentials_);
+ EXPECT_EQ(answer->connection_role, cricket::CONNECTIONROLE_ACTIVE);
+}
+
+TEST_F(TransportDescriptionFactoryTest, CreateAnswerToDtlsActiveOffer) {
+ f1_.set_secure(cricket::SEC_ENABLED);
+ f1_.set_certificate(cert1_);
+
+ f2_.set_secure(cricket::SEC_ENABLED);
+ f2_.set_certificate(cert2_);
+ cricket::TransportOptions options;
+ std::unique_ptr<TransportDescription> offer =
+ f1_.CreateOffer(options, nullptr, &ice_credentials_);
+ offer->connection_role = cricket::CONNECTIONROLE_ACTIVE;
+
+ std::unique_ptr<TransportDescription> answer =
+ f2_.CreateAnswer(offer.get(), options, false, nullptr, &ice_credentials_);
+ EXPECT_EQ(answer->connection_role, cricket::CONNECTIONROLE_PASSIVE);
+}
+
+TEST_F(TransportDescriptionFactoryTest, CreateAnswerToDtlsPassiveOffer) {
+ f1_.set_secure(cricket::SEC_ENABLED);
+ f1_.set_certificate(cert1_);
+
+ f2_.set_secure(cricket::SEC_ENABLED);
+ f2_.set_certificate(cert2_);
+ cricket::TransportOptions options;
+ std::unique_ptr<TransportDescription> offer =
+ f1_.CreateOffer(options, nullptr, &ice_credentials_);
+ offer->connection_role = cricket::CONNECTIONROLE_PASSIVE;
+
+ std::unique_ptr<TransportDescription> answer =
+ f2_.CreateAnswer(offer.get(), options, false, nullptr, &ice_credentials_);
+ EXPECT_EQ(answer->connection_role, cricket::CONNECTIONROLE_ACTIVE);
+}