tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 8d5ec70a721b81d1b3c72c7869edf2b325043676
parent bb77bbfc277cb407cbeea0eacb06a5d36b6a164c
Author: Dan Baker <dbaker@mozilla.com>
Date:   Wed, 22 Oct 2025 13:42:14 -0600

Bug 1995393 - Vendor libwebrtc from 77e84253e0

Upstream commit: https://webrtc.googlesource.com/src/+/77e84253e011d999a1647652bc5b40ad4030023b
    Add simplified WaitUntil variant to wait for a boolean condition

    This allows makes test bodies cleaner for such common use case
    eliminating extra IsTrue and IsRtcOk matchers.

    Bug: None
    Change-Id: I905143f5ccd0470e46437383e7fb5ec74e87a696
    Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/403160
    Reviewed-by: Evan Shrubsole <eshr@webrtc.org>
    Reviewed-by: Jeremy Leconte <jleconte@google.com>
    Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
    Cr-Commit-Position: refs/heads/main@{#45282}

Diffstat:
Mthird_party/libwebrtc/README.mozilla.last-vendor | 4++--
Mthird_party/libwebrtc/moz-patch-stack/s0027.patch | 2+-
Mthird_party/libwebrtc/moz-patch-stack/s0099.patch | 2+-
Mthird_party/libwebrtc/moz-patch-stack/s0103.patch | 2+-
Mthird_party/libwebrtc/test/BUILD.gn | 1+
Mthird_party/libwebrtc/test/network/network_emulation_pc_unittest.cc | 26++++++++------------------
Mthird_party/libwebrtc/test/wait_until.cc | 72++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Mthird_party/libwebrtc/test/wait_until.h | 76++++++++++++++++++++++++++++++++++++++++------------------------------------
Mthird_party/libwebrtc/test/wait_until_unittest.cc | 82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
9 files changed, 161 insertions(+), 106 deletions(-)

diff --git a/third_party/libwebrtc/README.mozilla.last-vendor b/third_party/libwebrtc/README.mozilla.last-vendor @@ -1,4 +1,4 @@ # ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/danielbaker/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc -libwebrtc updated from /Users/danielbaker/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2025-10-22T19:39:52.167456+00:00. +libwebrtc updated from /Users/danielbaker/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2025-10-22T19:42:03.164825+00:00. # base of lastest vendoring -483d22443d +77e84253e0 diff --git a/third_party/libwebrtc/moz-patch-stack/s0027.patch b/third_party/libwebrtc/moz-patch-stack/s0027.patch @@ -1199,7 +1199,7 @@ index c1181618e9..4a772795ed 100644 deps += [ "..:logging", diff --git a/test/BUILD.gn b/test/BUILD.gn -index 9edc60ad74..7bd39bd85b 100644 +index 75a3fbcdd9..f469105112 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -258,6 +258,7 @@ rtc_library("audio_test_common") { diff --git a/third_party/libwebrtc/moz-patch-stack/s0099.patch b/third_party/libwebrtc/moz-patch-stack/s0099.patch @@ -86,7 +86,7 @@ index 11c94ec229..df32a6863d 100644 if (!build_with_mozilla) { diff --git a/test/BUILD.gn b/test/BUILD.gn -index 7bd39bd85b..59bd007ce7 100644 +index f469105112..975dd7b222 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -470,6 +470,12 @@ rtc_source_set("test_support") { diff --git a/third_party/libwebrtc/moz-patch-stack/s0103.patch b/third_party/libwebrtc/moz-patch-stack/s0103.patch @@ -756,7 +756,7 @@ index 822b565610..f2ea548824 100644 import("../webrtc.gni") diff --git a/test/BUILD.gn b/test/BUILD.gn -index 59bd007ce7..0ac1cd374e 100644 +index 975dd7b222..d9f6c6d346 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -6,10 +6,10 @@ diff --git a/third_party/libwebrtc/test/BUILD.gn b/third_party/libwebrtc/test/BUILD.gn @@ -1503,6 +1503,7 @@ rtc_library("wait_until") { ] deps = [ ":test_support", + "../api:function_view", "../api:rtc_error", "../api:time_controller", "../api/units:time_delta", diff --git a/third_party/libwebrtc/test/network/network_emulation_pc_unittest.cc b/third_party/libwebrtc/test/network/network_emulation_pc_unittest.cc @@ -174,11 +174,8 @@ TEST(NetworkEmulationManagerPCTest, Run) { ASSERT_THAT(WaitUntil([&] { return alice->signaling_state(); }, Eq(PeerConnectionInterface::kStable)), IsRtcOk()); - ASSERT_THAT( - WaitUntil([&] { return alice->IsIceGatheringDone(); }, IsTrue()), - IsRtcOk()); - ASSERT_THAT(WaitUntil([&] { return bob->IsIceGatheringDone(); }, IsTrue()), - IsRtcOk()); + ASSERT_TRUE(WaitUntil([&] { return alice->IsIceGatheringDone(); })); + ASSERT_TRUE(WaitUntil([&] { return bob->IsIceGatheringDone(); })); // Connect an ICE candidate pairs. ASSERT_TRUE( @@ -186,10 +183,8 @@ TEST(NetworkEmulationManagerPCTest, Run) { ASSERT_TRUE( AddIceCandidates(alice.get(), bob->observer()->GetAllCandidates())); // This means that ICE and DTLS are connected. - ASSERT_THAT(WaitUntil([&] { return bob->IsIceConnected(); }, IsTrue()), - IsRtcOk()); - ASSERT_THAT(WaitUntil([&] { return alice->IsIceConnected(); }, IsTrue()), - IsRtcOk()); + ASSERT_TRUE(WaitUntil([&] { return bob->IsIceConnected(); })); + ASSERT_TRUE(WaitUntil([&] { return alice->IsIceConnected(); })); // Close peer connections alice->pc()->Close(); @@ -285,11 +280,8 @@ TEST(NetworkEmulationManagerPCTest, RunTURN) { ASSERT_THAT(WaitUntil([&] { return alice->signaling_state(); }, Eq(PeerConnectionInterface::kStable)), IsRtcOk()); - ASSERT_THAT( - WaitUntil([&] { return alice->IsIceGatheringDone(); }, IsTrue()), - IsRtcOk()); - ASSERT_THAT(WaitUntil([&] { return bob->IsIceGatheringDone(); }, IsTrue()), - IsRtcOk()); + ASSERT_TRUE(WaitUntil([&] { return alice->IsIceGatheringDone(); })); + ASSERT_TRUE(WaitUntil([&] { return bob->IsIceGatheringDone(); })); // Connect an ICE candidate pairs. ASSERT_TRUE( @@ -297,10 +289,8 @@ TEST(NetworkEmulationManagerPCTest, RunTURN) { ASSERT_TRUE( AddIceCandidates(alice.get(), bob->observer()->GetAllCandidates())); // This means that ICE and DTLS are connected. - ASSERT_THAT(WaitUntil([&] { return bob->IsIceConnected(); }, IsTrue()), - IsRtcOk()); - ASSERT_THAT(WaitUntil([&] { return alice->IsIceConnected(); }, IsTrue()), - IsRtcOk()); + ASSERT_TRUE(WaitUntil([&] { return bob->IsIceConnected(); })); + ASSERT_TRUE(WaitUntil([&] { return alice->IsIceConnected(); })); // Close peer connections alice->pc()->Close(); diff --git a/third_party/libwebrtc/test/wait_until.cc b/third_party/libwebrtc/test/wait_until.cc @@ -13,41 +13,61 @@ #include <variant> #include "absl/functional/overload.h" +#include "api/function_view.h" #include "api/test/time_controller.h" #include "api/units/time_delta.h" #include "api/units/timestamp.h" +#include "rtc_base/checks.h" #include "rtc_base/thread.h" #include "rtc_base/time_utils.h" #include "system_wrappers/include/clock.h" namespace webrtc { -namespace wait_until_internal { - -Timestamp GetTimeFromClockVariant(const ClockVariant& clock) { - return std::visit( - absl::Overload{ - [](const std::monostate&) { return Timestamp::Micros(TimeMicros()); }, - [](SimulatedClock* clock) { return clock->CurrentTime(); }, - [](TimeController* time_controller) { - return time_controller->GetClock()->CurrentTime(); - }, - [](auto* clock) { - return Timestamp::Micros(clock->TimeNanos() / 1000); - }, - }, - clock); -} -void AdvanceTimeOnClockVariant(ClockVariant& clock, TimeDelta delta) { - std::visit(absl::Overload{ - [&](const std::monostate&) { - Thread::Current()->ProcessMessages(0); - Thread::Current()->SleepMs(delta.ms()); - }, - [&](auto* clock) { clock->AdvanceTime(delta); }, - }, - clock); +[[nodiscard]] bool WaitUntil(FunctionView<bool()> fn, + WaitUntilSettings settings) { + if (std::holds_alternative<std::monostate>(settings.clock)) { + RTC_CHECK(Thread::Current()) << "A current thread is required. An " + "webrtc::AutoThread can work for tests."; + } + + auto now = [&] { + return std::visit( + absl::Overload{ + [](const std::monostate&) { + return Timestamp::Micros(TimeMicros()); + }, + [](SimulatedClock* clock) { return clock->CurrentTime(); }, + [](TimeController* time_controller) { + return time_controller->GetClock()->CurrentTime(); + }, + [](auto* clock) { + return Timestamp::Micros(clock->TimeNanos() / 1000); + }, + }, + settings.clock); + }; + + auto sleep = [&](TimeDelta delta) { + std::visit(absl::Overload{ + [&](const std::monostate&) { + Thread::Current()->ProcessMessages(0); + Thread::Current()->SleepMs(delta.ms()); + }, + [&](auto* clock) { clock->AdvanceTime(delta); }, + }, + settings.clock); + }; + + Timestamp deadline = now() + settings.timeout; + for (;;) { + if (fn()) { + return true; + } else if (now() >= deadline) { + return false; + } + sleep(settings.polling_interval); + } } -} // namespace wait_until_internal } // namespace webrtc diff --git a/third_party/libwebrtc/test/wait_until.h b/third_party/libwebrtc/test/wait_until.h @@ -11,18 +11,21 @@ #ifndef TEST_WAIT_UNTIL_H_ #define TEST_WAIT_UNTIL_H_ +#include <optional> #include <string> +#include <type_traits> +#include <utility> #include <variant> +#include "api/function_view.h" #include "api/rtc_error.h" #include "api/test/time_controller.h" #include "api/units/time_delta.h" -#include "api/units/timestamp.h" #include "rtc_base/checks.h" #include "rtc_base/fake_clock.h" -#include "rtc_base/thread.h" #include "system_wrappers/include/clock.h" #include "test/gmock.h" +#include "test/gtest.h" #include "test/wait_until_internal.h" // IWYU pragma: private namespace webrtc { @@ -33,11 +36,6 @@ using ClockVariant = std::variant<std::monostate, ThreadProcessingFakeClock*, TimeController*>; -namespace wait_until_internal { -Timestamp GetTimeFromClockVariant(const ClockVariant& clock); -void AdvanceTimeOnClockVariant(ClockVariant& clock, TimeDelta delta); -} // namespace wait_until_internal - struct WaitUntilSettings { // The maximum time to wait for the condition to be met. TimeDelta timeout = TimeDelta::Seconds(5); @@ -49,6 +47,16 @@ struct WaitUntilSettings { std::string result_name = "result"; }; +// Runs a function `fn`, until it returns true, or timeout from `settings`. +// Calls `fn` at least once. Returns true when `fn` return true, returns false +// after timeout if `fn` always returned false. +// +// Example: +// +// EXPECT_TRUE(WaitUntil([&] { return client.IsConnected(); }); +[[nodiscard]] bool WaitUntil(FunctionView<bool()> fn, + WaitUntilSettings settings = {}); + // Runs a function `fn`, which returns a result, until `matcher` matches the // result. // @@ -59,39 +67,35 @@ struct WaitUntilSettings { // Example: // // int counter = 0; -// RTCErrorOr<int> result = Waituntil([&] { return ++counter; }, Eq(3)) +// RTCErrorOr<int> result = WaitUntil([&] { return ++counter; }, Eq(3)) // EXPECT_THAT(result, IsOkAndHolds(3)); -template <typename Fn, typename Matcher> -[[nodiscard]] auto WaitUntil(const Fn& fn, - Matcher matcher, - WaitUntilSettings settings = {}) - -> RTCErrorOr<decltype(fn())> { - if (std::holds_alternative<std::monostate>(settings.clock)) { - RTC_CHECK(Thread::Current()) << "A current thread is required. An " - "webrtc::AutoThread can work for tests."; - } - - Timestamp start = - wait_until_internal::GetTimeFromClockVariant(settings.clock); - do { - auto result = fn(); - if (::testing::Value(result, matcher)) { - return result; - } - wait_until_internal::AdvanceTimeOnClockVariant(settings.clock, - settings.polling_interval); - } while (wait_until_internal::GetTimeFromClockVariant(settings.clock) < - start + settings.timeout); +template <typename Fn> +[[nodiscard]] RTCErrorOr<std::invoke_result_t<Fn>> WaitUntil( + const Fn& fn, + ::testing::Matcher<std::invoke_result_t<Fn>> matcher, + WaitUntilSettings settings = {}) { + // Wrap `result` into optional to support types that are not default + // constructable. + std::optional<std::invoke_result_t<Fn>> result; + bool ok = WaitUntil( + [&] { + // `emplace` instead of assigning to support return types that do not + // have an assign operator. + result.emplace(fn()); + return ::testing::Value(*result, matcher); + }, + settings); - // One more try after the last sleep. This failure will contain the error - // message. - auto result = fn(); - ::testing::StringMatchResultListener listener; - if (wait_until_internal::ExplainMatchResult(matcher, result, &listener, - settings.result_name)) { - return result; + // WaitUntil promise to call `fn` at least once and thus `result` is + // populated. + RTC_CHECK(result.has_value()); + if (ok) { + return *std::move(result); } + ::testing::StringMatchResultListener listener; + wait_until_internal::ExplainMatchResult(matcher, *result, &listener, + settings.result_name); return RTCError(RTCErrorType::INTERNAL_ERROR, listener.str()); } diff --git a/third_party/libwebrtc/test/wait_until_unittest.cc b/third_party/libwebrtc/test/wait_until_unittest.cc @@ -27,13 +27,24 @@ namespace webrtc { namespace { -using testing::_; -using testing::AllOf; -using testing::Eq; -using testing::Ge; -using testing::Gt; -using testing::Lt; -using testing::MatchesRegex; +using ::testing::_; +using ::testing::AllOf; +using ::testing::Eq; +using ::testing::Ge; +using ::testing::Gt; +using ::testing::Lt; +using ::testing::MatchesRegex; +using ::testing::Property; + +TEST(WaitUntilTest, ReturnsTrueWhenConditionIsMet) { + AutoThread thread; + + int counter = 0; + EXPECT_TRUE(WaitUntil([&] { return ++counter == 3; })); + + // Check that functor is not called after it returned true. + EXPECT_EQ(counter, 3); +} TEST(WaitUntilTest, ReturnsWhenConditionIsMet) { AutoThread thread; @@ -81,20 +92,22 @@ TEST(WaitUntilTest, ReturnsWhenConditionIsMetWithSimulatedClock) { SimulatedClock fake_clock(Timestamp::Millis(1337)); int counter = 0; - RTCErrorOr<int> result = - WaitUntil([&] { return ++counter; }, Eq(3), {.clock = &fake_clock}); - EXPECT_THAT(result, IsRtcOkAndHolds(3)); - // The fake clock should have advanced at least 2ms. - EXPECT_THAT(fake_clock.CurrentTime(), Ge(Timestamp::Millis(1339))); + EXPECT_TRUE(WaitUntil( + [&] { return ++counter == 3; }, + {.polling_interval = TimeDelta::Millis(10), .clock = &fake_clock})); + EXPECT_EQ(counter, 3); + // The fake clock should have advanced at least 2 polling intervals, 20ms. + EXPECT_THAT(fake_clock.CurrentTime(), Ge(Timestamp::Millis(1357))); } TEST(WaitUntilTest, ReturnsWhenConditionIsMetWithThreadProcessingFakeClock) { ScopedFakeClock fake_clock; int counter = 0; - RTCErrorOr<int> result = - WaitUntil([&] { return ++counter; }, Eq(3), {.clock = &fake_clock}); - EXPECT_THAT(result, IsRtcOkAndHolds(3)); + EXPECT_TRUE(WaitUntil( + [&] { return ++counter == 3; }, + {.polling_interval = TimeDelta::Millis(1), .clock = &fake_clock})); + EXPECT_EQ(counter, 3); // The fake clock should have advanced at least 2ms. EXPECT_THAT(Timestamp::Micros(fake_clock.TimeNanos() * 1000), Ge(Timestamp::Millis(1339))); @@ -104,22 +117,49 @@ TEST(WaitUntilTest, ReturnsWhenConditionIsMetWithFakeClock) { FakeClock fake_clock; int counter = 0; - RTCErrorOr<int> result = - WaitUntil([&] { return ++counter; }, Eq(3), {.clock = &fake_clock}); - EXPECT_THAT(result, IsRtcOkAndHolds(3)); + EXPECT_TRUE(WaitUntil( + [&] { return ++counter == 3; }, + {.polling_interval = TimeDelta::Millis(1), .clock = &fake_clock})); + EXPECT_EQ(counter, 3); // The fake clock should have advanced at least 2ms. EXPECT_THAT(Timestamp::Micros(fake_clock.TimeNanos() * 1000), Ge(Timestamp::Millis(1339))); } +// No default constuctor, not assignable, move-only type. +class CustomType { + public: + explicit CustomType(int value) : value_(value) {} + CustomType(CustomType&&) = default; + CustomType& operator=(CustomType&&) = delete; + CustomType() = delete; + + int value() const { return value_; } + + private: + const int value_; +}; + +TEST(WaitUntilTest, RequiresOnlyMoveCopyConstructionForReturnedType) { + AutoThread thread; + + int counter = 0; + RTCErrorOr<CustomType> result = + WaitUntil([&] { return CustomType(++counter); }, + Property(&CustomType::value, Eq(3))); + EXPECT_THAT(result, IsRtcOkAndHolds(Property(&CustomType::value, Eq(3)))); +} + TEST(WaitUntilTest, ReturnsWhenConditionIsMetWithSimulatedTimeController) { std::unique_ptr<TimeController> time_controller = CreateSimulatedTimeController(); int counter = 0; - RTCErrorOr<int> result = WaitUntil([&] { return ++counter; }, Eq(3), - {.clock = time_controller.get()}); - EXPECT_THAT(result, IsRtcOkAndHolds(3)); + EXPECT_TRUE(WaitUntil([&] { return ++counter == 3; }, + {.polling_interval = TimeDelta::Millis(1), + .clock = time_controller.get()})); + EXPECT_EQ(counter, 3); + // The fake clock should have advanced at least 2ms. EXPECT_THAT(time_controller->GetClock()->CurrentTime(), Ge(Timestamp::Millis(1339)));