shill: Use TaskEnvironment for EventDispatcherForTest

Currently, EventDispatcherForTest initializes a SingleThreadTaskExecutor
internally while the latter is not intended for test usage, according to
its comment. This patch changes to use base::test::TaskEnvironment,
which gives us opportunities to have a better unit test, e.g., easy to
test PostDelayedTask().

Also modifies DeviceInfoTest according to this change.

This change will not affect other unit tests.

BUG=None
TEST=shill_unittest

Change-Id: I8af92f4732a224938d6cdf7725b19a55a41773dd
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2474049
Tested-by: Jie Jiang <jiejiang@chromium.org>
Commit-Queue: Jie Jiang <jiejiang@chromium.org>
Reviewed-by: Garrick Evans <garrick@chromium.org>
diff --git a/shill/device_info.h b/shill/device_info.h
index 1b9e273..7a36abf 100644
--- a/shill/device_info.h
+++ b/shill/device_info.h
@@ -129,7 +129,6 @@
   FRIEND_TEST(DeviceInfoTest, GetUninitializedTechnologies);
   FRIEND_TEST(DeviceInfoTest, HasSubdir);           // For HasSubdir.
   FRIEND_TEST(DeviceInfoTest, IPv6AddressChanged);  // For infos_.
-  FRIEND_TEST(DeviceInfoTest, RequestLinkStatistics);
   FRIEND_TEST(DeviceInfoTest, StartStop);
   FRIEND_TEST(DeviceInfoTest, IPv6DnsServerAddressesChanged);  // For infos_.
   FRIEND_TEST(DeviceInfoMockedGetUserId,
diff --git a/shill/device_info_test.cc b/shill/device_info_test.cc
index 42385ee..c6acfbf 100644
--- a/shill/device_info_test.cc
+++ b/shill/device_info_test.cc
@@ -67,14 +67,6 @@
 
 namespace shill {
 
-class TestEventDispatcherForDeviceInfo : public EventDispatcherForTest {
- public:
-  MOCK_METHOD(void,
-              PostDelayedTask,
-              (const base::Location&, const base::Closure&, int64_t),
-              (override));
-};
-
 class DeviceInfoTest : public Test {
  public:
   DeviceInfoTest()
@@ -169,7 +161,7 @@
   MockMetrics metrics_;
   StrictMock<MockManager> manager_;
   DeviceInfo device_info_;
-  TestEventDispatcherForDeviceInfo dispatcher_;
+  EventDispatcherForTest dispatcher_;
   MockRoutingTable routing_table_;
 #if !defined(DISABLE_WIFI)
   MockNetlinkManager netlink_manager_;
@@ -257,19 +249,29 @@
 }
 
 TEST_F(DeviceInfoTest, StartStop) {
+  auto& task_environment = dispatcher_.task_environment();
   EXPECT_EQ(nullptr, device_info_.link_listener_);
   EXPECT_EQ(nullptr, device_info_.address_listener_);
   EXPECT_TRUE(device_info_.infos_.empty());
 
   EXPECT_CALL(rtnl_handler_, RequestDump(RTNLHandler::kRequestLink |
                                          RTNLHandler::kRequestAddr));
-  EXPECT_CALL(dispatcher_, PostDelayedTask(_, _, _));
   device_info_.Start();
   EXPECT_NE(nullptr, device_info_.link_listener_);
   EXPECT_NE(nullptr, device_info_.address_listener_);
   EXPECT_TRUE(device_info_.infos_.empty());
   Mock::VerifyAndClearExpectations(&rtnl_handler_);
 
+  // Start() should set up a periodic task to request link statistics.
+  EXPECT_EQ(1, task_environment.GetPendingMainThreadTaskCount());
+  EXPECT_CALL(rtnl_handler_, RequestDump(RTNLHandler::kRequestLink));
+  task_environment.FastForwardBy(
+      task_environment.NextMainThreadPendingTaskDelay());
+  EXPECT_EQ(1, task_environment.GetPendingMainThreadTaskCount());
+  EXPECT_CALL(rtnl_handler_, RequestDump(RTNLHandler::kRequestLink));
+  task_environment.FastForwardBy(
+      task_environment.NextMainThreadPendingTaskDelay());
+
   CreateInterfaceAddress();
   EXPECT_FALSE(device_info_.infos_.empty());
 
@@ -287,12 +289,6 @@
   device_info_.RegisterDevice(device0);
 }
 
-TEST_F(DeviceInfoTest, RequestLinkStatistics) {
-  EXPECT_CALL(rtnl_handler_, RequestDump(RTNLHandler::kRequestLink));
-  EXPECT_CALL(dispatcher_, PostDelayedTask(_, _, _));
-  device_info_.RequestLinkStatistics();
-}
-
 TEST_F(DeviceInfoTest, DeviceEnumeration) {
   unique_ptr<RTNLMessage> message = BuildLinkMessage(RTNLMessage::kModeAdd);
   message->set_link_status(RTNLMessage::LinkStatus(0, IFF_LOWER_UP, 0));
@@ -590,13 +586,13 @@
 #endif  // DISABLE_CELLULAR
   EXPECT_CALL(routing_table_, FlushRoutes(_)).Times(0);
   EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(_, _)).Times(0);
-  EXPECT_CALL(dispatcher_, PostDelayedTask(_, _, _));
   EXPECT_TRUE(GetDelayedDevices().empty());
   EXPECT_FALSE(CreateDevice(kTestDeviceName, "address", kTestDeviceIndex,
                             Technology::kCDCEthernet));
   EXPECT_FALSE(GetDelayedDevices().empty());
   EXPECT_EQ(1, GetDelayedDevices().size());
   EXPECT_EQ(kTestDeviceIndex, *GetDelayedDevices().begin());
+  EXPECT_EQ(1, dispatcher_.task_environment().GetPendingMainThreadTaskCount());
 }
 
 TEST_F(DeviceInfoTest, CreateDeviceUnknown) {
diff --git a/shill/test_event_dispatcher.h b/shill/test_event_dispatcher.h
index efbb993..468f616 100644
--- a/shill/test_event_dispatcher.h
+++ b/shill/test_event_dispatcher.h
@@ -13,17 +13,18 @@
 
 namespace shill {
 
-// Event dispatcher with message loop for testing.
+// Event dispatcher with base::test::TaskEnvironment for testing.
 class EventDispatcherForTest : public EventDispatcher {
  public:
-  EventDispatcherForTest() { chromeos_message_loop_.SetAsCurrent(); }
+  EventDispatcherForTest() = default;
   ~EventDispatcherForTest() override = default;
 
+  base::test::TaskEnvironment& task_environment() { return task_environment_; }
+
  private:
-  // Message loop for testing.
-  base::SingleThreadTaskExecutor task_executor_{base::MessagePumpType::IO};
-  // The chromeos wrapper for the main message loop.
-  brillo::BaseMessageLoop chromeos_message_loop_{task_executor_.task_runner()};
+  base::test::TaskEnvironment task_environment_{
+      base::test::TaskEnvironment::TimeSource::MOCK_TIME,
+      base::test::TaskEnvironment::MainThreadType::IO};
 
   DISALLOW_COPY_AND_ASSIGN(EventDispatcherForTest);
 };