local_muter_unittest.cc 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. // Copyright 2018 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "services/audio/local_muter.h"
  5. #include <memory>
  6. #include "base/test/mock_callback.h"
  7. #include "base/test/task_environment.h"
  8. #include "base/unguessable_token.h"
  9. #include "services/audio/loopback_coordinator.h"
  10. #include "services/audio/loopback_group_member.h"
  11. #include "services/audio/test/mock_group_member.h"
  12. #include "testing/gmock/include/gmock/gmock.h"
  13. #include "testing/gtest/include/gtest/gtest.h"
  14. using base::UnguessableToken;
  15. using testing::InvokeWithoutArgs;
  16. using testing::Mock;
  17. using testing::StrictMock;
  18. namespace audio {
  19. namespace {
  20. TEST(LocalMuterTest, MutesExistingMembers) {
  21. LoopbackCoordinator coordinator;
  22. // Create a group with two members.
  23. const UnguessableToken group_id = UnguessableToken::Create();
  24. StrictMock<MockGroupMember> member1;
  25. StrictMock<MockGroupMember> member2;
  26. // Create another group with one member, which should never have its mute
  27. // state changed.
  28. const UnguessableToken other_group_id = UnguessableToken::Create();
  29. ASSERT_NE(group_id, other_group_id);
  30. StrictMock<MockGroupMember> non_member;
  31. EXPECT_CALL(non_member, StartMuting()).Times(0);
  32. EXPECT_CALL(non_member, StopMuting()).Times(0);
  33. // When the members join the group, no mute change should occur.
  34. coordinator.RegisterMember(group_id, &member1);
  35. coordinator.RegisterMember(group_id, &member2);
  36. // When the muter is created, both members should be muted.
  37. EXPECT_CALL(member1, StartMuting());
  38. EXPECT_CALL(member2, StartMuting());
  39. auto muter = std::make_unique<LocalMuter>(&coordinator, group_id);
  40. Mock::VerifyAndClearExpectations(&member1);
  41. Mock::VerifyAndClearExpectations(&member2);
  42. // When the muter is destroyed, both members should be un-muted.
  43. EXPECT_CALL(member1, StopMuting());
  44. EXPECT_CALL(member2, StopMuting());
  45. muter = nullptr;
  46. Mock::VerifyAndClearExpectations(&member1);
  47. Mock::VerifyAndClearExpectations(&member2);
  48. coordinator.UnregisterMember(group_id, &member1);
  49. coordinator.UnregisterMember(group_id, &member2);
  50. }
  51. TEST(LocalMuterTest, MutesJoiningMembers) {
  52. LoopbackCoordinator coordinator;
  53. const UnguessableToken group_id = UnguessableToken::Create();
  54. LocalMuter muter(&coordinator, group_id);
  55. StrictMock<MockGroupMember> member;
  56. // Since muting is in-effect, the group member is immediately muted when
  57. // joining the group.
  58. EXPECT_CALL(member, StartMuting());
  59. coordinator.RegisterMember(group_id, &member);
  60. Mock::VerifyAndClearExpectations(&member);
  61. // Leaving the group should have no effect on the mute state of the member.
  62. EXPECT_CALL(member, StartMuting()).Times(0);
  63. EXPECT_CALL(member, StopMuting()).Times(0);
  64. coordinator.UnregisterMember(group_id, &member);
  65. Mock::VerifyAndClearExpectations(&member);
  66. }
  67. TEST(LocalMuter, UnmutesWhenLastBindingIsLost) {
  68. base::test::TaskEnvironment task_environment;
  69. LoopbackCoordinator coordinator;
  70. const UnguessableToken group_id = UnguessableToken::Create();
  71. // Later in this test, once both bindings have been closed, the following
  72. // callback should be run. The callback will delete the LocalMuter in the same
  73. // stack as the mojo connection error handler, just as would take place in the
  74. // live build.
  75. auto muter = std::make_unique<LocalMuter>(&coordinator, group_id);
  76. base::MockCallback<base::RepeatingClosure> callback;
  77. EXPECT_CALL(callback, Run()).WillOnce(InvokeWithoutArgs([&muter]() {
  78. muter.reset();
  79. }));
  80. muter->SetAllBindingsLostCallback(callback.Get());
  81. // Create two bindings to the muter.
  82. mojo::AssociatedRemote<media::mojom::LocalMuter> remote_muter1;
  83. muter->AddReceiver(remote_muter1.BindNewEndpointAndPassReceiver());
  84. mojo::AssociatedRemote<media::mojom::LocalMuter> remote_muter2;
  85. muter->AddReceiver(remote_muter2.BindNewEndpointAndPassReceiver());
  86. // A member joins the group and should be muted.
  87. StrictMock<MockGroupMember> member;
  88. EXPECT_CALL(member, StartMuting());
  89. coordinator.RegisterMember(group_id, &member);
  90. Mock::VerifyAndClearExpectations(&member);
  91. // Nothing happens to the member when one of the bindings is closed.
  92. EXPECT_CALL(member, StopMuting()).Times(0);
  93. remote_muter1.reset();
  94. task_environment.RunUntilIdle(); // Propagate mojo tasks.
  95. Mock::VerifyAndClearExpectations(&member);
  96. // The member is unmuted once the second binding is closed.
  97. EXPECT_CALL(member, StopMuting());
  98. remote_muter2.reset();
  99. task_environment.RunUntilIdle(); // Propagate mojo tasks.
  100. Mock::VerifyAndClearExpectations(&member);
  101. // At this point, the LocalMuter should have been destroyed.
  102. EXPECT_FALSE(muter);
  103. coordinator.UnregisterMember(group_id, &member);
  104. }
  105. } // namespace
  106. } // namespace audio