1// Copyright (c) 2012 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
5#include "ppapi/tests/test_network_monitor.h"
6
7#include <string.h>
8
9#include "ppapi/cpp/completion_callback.h"
10#include "ppapi/cpp/instance_handle.h"
11#include "ppapi/cpp/module.h"
12#include "ppapi/cpp/net_address.h"
13#include "ppapi/cpp/network_list.h"
14#include "ppapi/cpp/network_monitor.h"
15#include "ppapi/tests/test_utils.h"
16#include "ppapi/tests/testing_instance.h"
17
18REGISTER_TEST_CASE(NetworkMonitor);
19
20namespace {
21
22class MonitorDeletionCallbackDelegate
23    : public TestCompletionCallback::Delegate {
24 public:
25  explicit MonitorDeletionCallbackDelegate(pp::NetworkMonitor* monitor)
26      : monitor_(monitor) {
27  }
28
29  // TestCompletionCallback::Delegate interface.
30  virtual void OnCallback(void* user_data, int32_t result) {
31    delete monitor_;
32  }
33
34 private:
35  pp::NetworkMonitor* monitor_;
36};
37
38}  // namespace
39
40TestNetworkMonitor::TestNetworkMonitor(TestingInstance* instance)
41    : TestCase(instance) {
42}
43
44bool TestNetworkMonitor::Init() {
45  if (!pp::NetworkMonitor::IsAvailable())
46    return false;
47
48  return CheckTestingInterface();
49}
50
51void TestNetworkMonitor::RunTests(const std::string& filter) {
52  RUN_TEST_FORCEASYNC_AND_NOT(Basic, filter);
53  RUN_TEST_FORCEASYNC_AND_NOT(2Monitors, filter);
54  RUN_TEST_FORCEASYNC_AND_NOT(DeleteInCallback, filter);
55}
56
57std::string TestNetworkMonitor::VerifyNetworkList(
58    const pp::NetworkList& network_list) {
59  // Verify that there is at least one network interface.
60  size_t count = network_list.GetCount();
61  ASSERT_TRUE(count >= 1U);
62
63  // Iterate over all interfaces and verify their properties.
64  for (size_t iface = 0; iface < count; ++iface) {
65    // Verify that the first interface has at least one address.
66    std::vector<pp::NetAddress> addresses;
67    network_list.GetIpAddresses(iface, &addresses);
68    ASSERT_TRUE(addresses.size() >= 1U);
69    // Verify that the addresses are valid.
70    for (size_t i = 0; i < addresses.size(); ++i) {
71      PP_NetAddress_Family family = addresses[i].GetFamily();
72
73      switch (family) {
74        case PP_NETADDRESS_FAMILY_IPV4: {
75          PP_NetAddress_IPv4 ipv4;
76          ASSERT_TRUE(addresses[i].DescribeAsIPv4Address(&ipv4));
77
78          // Verify that the address is not zero.
79          bool all_zeros = true;
80          for (size_t j = 0; j < sizeof(ipv4.addr); ++j) {
81            if (ipv4.addr[j] != 0) {
82              all_zeros = false;
83              break;
84            }
85          }
86          ASSERT_TRUE(!all_zeros);
87
88          // Verify that port is set to 0.
89          ASSERT_TRUE(ipv4.port == 0);
90          break;
91        }
92
93        case PP_NETADDRESS_FAMILY_IPV6: {
94          PP_NetAddress_IPv6 ipv6;
95          ASSERT_TRUE(addresses[i].DescribeAsIPv6Address(&ipv6));
96
97          // Verify that the address is not zero.
98          bool all_zeros = true;
99          for (size_t j = 0; j < sizeof(ipv6.addr); ++j) {
100            if (ipv6.addr[j] != 0) {
101              all_zeros = false;
102              break;
103            }
104          }
105          ASSERT_TRUE(!all_zeros);
106
107          // Verify that port is set to 0.
108          ASSERT_TRUE(ipv6.port == 0);
109          break;
110        }
111
112        default:
113          ASSERT_TRUE(false);
114      }
115    }
116
117    // Verify that each interface has a unique name and a display name.
118    ASSERT_FALSE(network_list.GetName(iface).empty());
119    ASSERT_FALSE(network_list.GetDisplayName(iface).empty());
120
121    PP_NetworkList_Type type = network_list.GetType(iface);
122    ASSERT_TRUE(type >= PP_NETWORKLIST_TYPE_UNKNOWN);
123    ASSERT_TRUE(type <= PP_NETWORKLIST_TYPE_CELLULAR);
124
125    PP_NetworkList_State state = network_list.GetState(iface);
126    ASSERT_TRUE(state >= PP_NETWORKLIST_STATE_DOWN);
127    ASSERT_TRUE(state <= PP_NETWORKLIST_STATE_UP);
128  }
129
130  PASS();
131}
132
133std::string TestNetworkMonitor::TestBasic() {
134  TestCompletionCallbackWithOutput<pp::NetworkList> test_callback(
135      instance_->pp_instance());
136  pp::NetworkMonitor network_monitor(instance_);
137  test_callback.WaitForResult(
138      network_monitor.UpdateNetworkList(test_callback.GetCallback()));
139
140  ASSERT_EQ(PP_OK, test_callback.result());
141  ASSERT_SUBTEST_SUCCESS(VerifyNetworkList(test_callback.output()));
142
143  PASS();
144}
145
146std::string TestNetworkMonitor::Test2Monitors() {
147  TestCompletionCallbackWithOutput<pp::NetworkList> test_callback(
148     instance_->pp_instance());
149  pp::NetworkMonitor network_monitor(instance_);
150  test_callback.WaitForResult(
151      network_monitor.UpdateNetworkList(test_callback.GetCallback()));
152
153  ASSERT_EQ(PP_OK, test_callback.result());
154  ASSERT_SUBTEST_SUCCESS(VerifyNetworkList(test_callback.output()));
155
156  TestCompletionCallbackWithOutput<pp::NetworkList> test_callback_2(
157      instance_->pp_instance());
158  pp::NetworkMonitor network_monitor_2(instance_);
159  test_callback_2.WaitForResult(
160      network_monitor_2.UpdateNetworkList(test_callback_2.GetCallback()));
161
162  ASSERT_EQ(PP_OK, test_callback_2.result());
163  ASSERT_SUBTEST_SUCCESS(VerifyNetworkList(test_callback_2.output()));
164
165  PASS();
166}
167
168std::string TestNetworkMonitor::TestDeleteInCallback() {
169  pp::NetworkMonitor* network_monitor =
170      new pp::NetworkMonitor(instance_);
171  MonitorDeletionCallbackDelegate deletion_delegate(network_monitor);
172  TestCompletionCallbackWithOutput<pp::NetworkList> test_callback(
173      instance_->pp_instance());
174  test_callback.SetDelegate(&deletion_delegate);
175  test_callback.WaitForResult(
176      network_monitor->UpdateNetworkList(test_callback.GetCallback()));
177
178  ASSERT_EQ(PP_OK, test_callback.result());
179  ASSERT_SUBTEST_SUCCESS(VerifyNetworkList(test_callback.output()));
180
181  PASS();
182}
183