blob: 28e10d9c15ba4acec26d7ca86a9d0e8be87f1f2f [file] [log] [blame]
Thieu Le3426c8f2012-01-11 17:35:11 -08001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Thieu Le48e6d6d2011-12-06 00:40:27 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "shill/metrics.h"
6
Thieu Le26fc01b2013-01-28 12:08:48 -08007#include <string>
8
Thieu Le48e6d6d2011-12-06 00:40:27 +00009#include <chromeos/dbus/service_constants.h>
10#include <metrics/metrics_library_mock.h>
Thieu Lea20cbc22012-01-09 22:01:43 +000011#include <metrics/timer_mock.h>
Thieu Le48e6d6d2011-12-06 00:40:27 +000012
Thieu Le6c1e3bb2013-02-06 15:20:35 -080013#include "shill/mock_control.h"
Paul Stewartc43cbbe2013-04-11 06:29:30 -070014#include "shill/mock_eap_credentials.h"
Thieu Le6c1e3bb2013-02-06 15:20:35 -080015#include "shill/mock_event_dispatcher.h"
16#include "shill/mock_glib.h"
17#include "shill/mock_manager.h"
Thieu Le48e6d6d2011-12-06 00:40:27 +000018#include "shill/mock_service.h"
19#include "shill/mock_wifi_service.h"
Thieu Le48e6d6d2011-12-06 00:40:27 +000020
Thieu Le26fc01b2013-01-28 12:08:48 -080021using std::string;
22
Thieu Le48e6d6d2011-12-06 00:40:27 +000023using testing::_;
Thieu Leb84ba342012-03-02 15:15:19 -080024using testing::DoAll;
Thieu Le48e6d6d2011-12-06 00:40:27 +000025using testing::Ge;
Thieu Leb84ba342012-03-02 15:15:19 -080026using testing::Mock;
Thieu Le48e6d6d2011-12-06 00:40:27 +000027using testing::Return;
Thieu Leb84ba342012-03-02 15:15:19 -080028using testing::SetArgumentPointee;
Thieu Le48e6d6d2011-12-06 00:40:27 +000029using testing::Test;
30
31namespace shill {
32
Thieu Le6c1e3bb2013-02-06 15:20:35 -080033class MetricsTest : public Test {
Thieu Le48e6d6d2011-12-06 00:40:27 +000034 public:
35 MetricsTest()
Thieu Le6c1e3bb2013-02-06 15:20:35 -080036 : manager_(&control_interface_,
37 &dispatcher_,
38 &metrics_,
39 &glib_),
40 metrics_(&dispatcher_),
41 service_(new MockService(&control_interface_,
42 &dispatcher_,
Thieu Le3426c8f2012-01-11 17:35:11 -080043 &metrics_,
Thieu Le6c1e3bb2013-02-06 15:20:35 -080044 &manager_)),
mukesh agrawalcbfb34e2013-04-17 19:33:25 -070045 open_wifi_service_(new MockWiFiService(&control_interface_,
46 &dispatcher_,
47 &metrics_,
48 &manager_,
49 manager_.wifi_provider(),
50 ssid_,
51 flimflam::kModeManaged,
52 flimflam::kSecurityNone,
53 false)),
54 wep_wifi_service_(new MockWiFiService(&control_interface_,
55 &dispatcher_,
56 &metrics_,
57 &manager_,
58 manager_.wifi_provider(),
59 ssid_,
60 flimflam::kModeManaged,
61 flimflam::kSecurityWep,
62 false)),
63 eap_wifi_service_(new MockWiFiService(&control_interface_,
64 &dispatcher_,
65 &metrics_,
66 &manager_,
67 manager_.wifi_provider(),
68 ssid_,
69 flimflam::kModeManaged,
70 flimflam::kSecurity8021x,
71 false)),
Paul Stewartc43cbbe2013-04-11 06:29:30 -070072 eap_(new MockEapCredentials()) {}
Thieu Le48e6d6d2011-12-06 00:40:27 +000073
74 virtual ~MetricsTest() {}
75
76 virtual void SetUp() {
77 metrics_.set_library(&library_);
mukesh agrawalcbfb34e2013-04-17 19:33:25 -070078 eap_wifi_service_->eap_.reset(eap_); // Passes ownership.
Darin Petkov58f0b6d2012-06-12 12:52:30 +020079 metrics_.collect_bootstats_ = false;
Thieu Le48e6d6d2011-12-06 00:40:27 +000080 }
81
82 protected:
Paul Stewarte4cedde2013-07-17 08:56:44 -070083 void ExpectCommonPostReady(Metrics::WiFiApMode ap_mode,
84 Metrics::WiFiChannel channel,
Thieu Leb84ba342012-03-02 15:15:19 -080085 Metrics::WiFiNetworkPhyMode mode,
Paul Stewart23b393a2012-09-25 21:21:06 -070086 Metrics::WiFiSecurity security,
87 int signal_strength) {
Paul Stewarte4cedde2013-07-17 08:56:44 -070088 EXPECT_CALL(library_, SendEnumToUMA("Network.Shill.Wifi.ApMode",
89 ap_mode,
90 Metrics::kWiFiApModeMax));
Thieu Leb84ba342012-03-02 15:15:19 -080091 EXPECT_CALL(library_, SendEnumToUMA("Network.Shill.Wifi.Channel",
92 channel,
93 Metrics::kMetricNetworkChannelMax));
94 EXPECT_CALL(library_, SendEnumToUMA("Network.Shill.Wifi.PhyMode",
95 mode,
96 Metrics::kWiFiNetworkPhyModeMax));
97 EXPECT_CALL(library_, SendEnumToUMA("Network.Shill.Wifi.Security",
98 security,
99 Metrics::kWiFiSecurityMax));
Paul Stewart23b393a2012-09-25 21:21:06 -0700100 EXPECT_CALL(library_,
101 SendToUMA("Network.Shill.Wifi.SignalStrength",
102 signal_strength,
103 Metrics::kMetricNetworkSignalStrengthMin,
104 Metrics::kMetricNetworkSignalStrengthMax,
105 Metrics::kMetricNetworkSignalStrengthNumBuckets));
Thieu Leb84ba342012-03-02 15:15:19 -0800106 }
107
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800108 MockControl control_interface_;
109 MockEventDispatcher dispatcher_;
110 MockGLib glib_;
111 MockManager manager_;
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700112 Metrics metrics_; // This must be destroyed after all |service_|s.
Thieu Le48e6d6d2011-12-06 00:40:27 +0000113 MetricsLibraryMock library_;
114 scoped_refptr<MockService> service_;
Thieu Le48e6d6d2011-12-06 00:40:27 +0000115 const std::vector<uint8_t> ssid_;
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700116 scoped_refptr<MockWiFiService> open_wifi_service_;
117 scoped_refptr<MockWiFiService> wep_wifi_service_;
118 scoped_refptr<MockWiFiService> eap_wifi_service_;
119 MockEapCredentials *eap_; // Owned by |eap_wifi_service_|.
Thieu Le48e6d6d2011-12-06 00:40:27 +0000120};
121
122TEST_F(MetricsTest, TimeToConfig) {
123 EXPECT_CALL(library_, SendToUMA("Network.Shill.Unknown.TimeToConfig",
124 Ge(0),
Thieu Lea20cbc22012-01-09 22:01:43 +0000125 Metrics::kTimerHistogramMillisecondsMin,
126 Metrics::kTimerHistogramMillisecondsMax,
Thieu Le48e6d6d2011-12-06 00:40:27 +0000127 Metrics::kTimerHistogramNumBuckets));
128 metrics_.RegisterService(service_);
129 metrics_.NotifyServiceStateChanged(service_, Service::kStateConfiguring);
Paul Stewart20088d82012-02-16 06:58:55 -0800130 metrics_.NotifyServiceStateChanged(service_, Service::kStateConnected);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000131}
132
133TEST_F(MetricsTest, TimeToPortal) {
134 EXPECT_CALL(library_, SendToUMA("Network.Shill.Unknown.TimeToPortal",
135 Ge(0),
Thieu Lea20cbc22012-01-09 22:01:43 +0000136 Metrics::kTimerHistogramMillisecondsMin,
137 Metrics::kTimerHistogramMillisecondsMax,
Thieu Le48e6d6d2011-12-06 00:40:27 +0000138 Metrics::kTimerHistogramNumBuckets));
139 metrics_.RegisterService(service_);
Paul Stewart20088d82012-02-16 06:58:55 -0800140 metrics_.NotifyServiceStateChanged(service_, Service::kStateConnected);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000141 metrics_.NotifyServiceStateChanged(service_, Service::kStatePortal);
142}
143
144TEST_F(MetricsTest, TimeToOnline) {
145 EXPECT_CALL(library_, SendToUMA("Network.Shill.Unknown.TimeToOnline",
146 Ge(0),
Thieu Lea20cbc22012-01-09 22:01:43 +0000147 Metrics::kTimerHistogramMillisecondsMin,
148 Metrics::kTimerHistogramMillisecondsMax,
Thieu Le48e6d6d2011-12-06 00:40:27 +0000149 Metrics::kTimerHistogramNumBuckets));
150 metrics_.RegisterService(service_);
Paul Stewart20088d82012-02-16 06:58:55 -0800151 metrics_.NotifyServiceStateChanged(service_, Service::kStateConnected);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000152 metrics_.NotifyServiceStateChanged(service_, Service::kStateOnline);
153}
154
155TEST_F(MetricsTest, ServiceFailure) {
156 EXPECT_CALL(*service_.get(), failure())
Paul Stewartf2d60912012-07-15 08:37:30 -0700157 .WillRepeatedly(Return(Service::kFailureBadPassphrase));
Thieu Le48e6d6d2011-12-06 00:40:27 +0000158 EXPECT_CALL(library_, SendEnumToUMA(Metrics::kMetricNetworkServiceErrors,
Paul Stewartf2d60912012-07-15 08:37:30 -0700159 Service::kFailureBadPassphrase,
Thieu Le48e6d6d2011-12-06 00:40:27 +0000160 Metrics::kMetricNetworkServiceErrorsMax));
161 metrics_.RegisterService(service_);
162 metrics_.NotifyServiceStateChanged(service_, Service::kStateFailure);
163}
164
165TEST_F(MetricsTest, WiFiServiceTimeToJoin) {
166 EXPECT_CALL(library_, SendToUMA("Network.Shill.Wifi.TimeToJoin",
167 Ge(0),
Thieu Lea20cbc22012-01-09 22:01:43 +0000168 Metrics::kTimerHistogramMillisecondsMin,
169 Metrics::kTimerHistogramMillisecondsMax,
Thieu Le48e6d6d2011-12-06 00:40:27 +0000170 Metrics::kTimerHistogramNumBuckets));
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700171 metrics_.RegisterService(open_wifi_service_);
172 metrics_.NotifyServiceStateChanged(open_wifi_service_,
173 Service::kStateAssociating);
174 metrics_.NotifyServiceStateChanged(open_wifi_service_,
175 Service::kStateConfiguring);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000176}
177
Thieu Lead1ec2c2012-01-05 23:39:48 +0000178TEST_F(MetricsTest, WiFiServicePostReady) {
Thieu Leb84ba342012-03-02 15:15:19 -0800179 base::TimeDelta non_zero_time_delta = base::TimeDelta::FromMilliseconds(1);
180 chromeos_metrics::TimerMock *mock_time_resume_to_ready_timer =
181 new chromeos_metrics::TimerMock;
182 metrics_.set_time_resume_to_ready_timer(mock_time_resume_to_ready_timer);
183
Paul Stewart23b393a2012-09-25 21:21:06 -0700184 const int kStrength = -42;
Paul Stewarte4cedde2013-07-17 08:56:44 -0700185 ExpectCommonPostReady(Metrics::kWiFiApModeManaged,
186 Metrics::kWiFiChannel2412,
Thieu Leb84ba342012-03-02 15:15:19 -0800187 Metrics::kWiFiNetworkPhyMode11a,
Paul Stewart23b393a2012-09-25 21:21:06 -0700188 Metrics::kWiFiSecurityWep,
189 -kStrength);
Thieu Leb84ba342012-03-02 15:15:19 -0800190 EXPECT_CALL(library_, SendToUMA("Network.Shill.Wifi.TimeResumeToReady",
191 _, _, _, _)).Times(0);
Paul Stewart21f40962013-03-01 14:27:28 -0800192 EXPECT_CALL(library_, SendEnumToUMA("Network.Shill.Wifi.EapOuterProtocol",
193 _, _)).Times(0);
194 EXPECT_CALL(library_, SendEnumToUMA("Network.Shill.Wifi.EapInnerProtocol",
195 _, _)).Times(0);
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700196 wep_wifi_service_->frequency_ = 2412;
197 wep_wifi_service_->physical_mode_ = Metrics::kWiFiNetworkPhyMode11a;
198 wep_wifi_service_->raw_signal_strength_ = kStrength;
199 metrics_.RegisterService(wep_wifi_service_);
200 metrics_.NotifyServiceStateChanged(wep_wifi_service_,
201 Service::kStateConnected);
Thieu Leb84ba342012-03-02 15:15:19 -0800202 Mock::VerifyAndClearExpectations(&library_);
203
204 // Simulate a system suspend, resume and an AP reconnect.
Paul Stewarte4cedde2013-07-17 08:56:44 -0700205 ExpectCommonPostReady(Metrics::kWiFiApModeManaged,
206 Metrics::kWiFiChannel2412,
Thieu Leb84ba342012-03-02 15:15:19 -0800207 Metrics::kWiFiNetworkPhyMode11a,
Paul Stewart23b393a2012-09-25 21:21:06 -0700208 Metrics::kWiFiSecurityWep,
209 -kStrength);
Thieu Leb84ba342012-03-02 15:15:19 -0800210 EXPECT_CALL(library_, SendToUMA("Network.Shill.Wifi.TimeResumeToReady",
211 Ge(0),
212 Metrics::kTimerHistogramMillisecondsMin,
213 Metrics::kTimerHistogramMillisecondsMax,
214 Metrics::kTimerHistogramNumBuckets));
215 EXPECT_CALL(*mock_time_resume_to_ready_timer, GetElapsedTime(_)).
216 WillOnce(DoAll(SetArgumentPointee<0>(non_zero_time_delta), Return(true)));
217 metrics_.NotifyPowerStateChange(PowerManagerProxyDelegate::kMem);
218 metrics_.NotifyPowerStateChange(PowerManagerProxyDelegate::kOn);
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700219 metrics_.NotifyServiceStateChanged(wep_wifi_service_,
220 Service::kStateConnected);
Thieu Leb84ba342012-03-02 15:15:19 -0800221 Mock::VerifyAndClearExpectations(&library_);
222 Mock::VerifyAndClearExpectations(mock_time_resume_to_ready_timer);
223
224 // Make sure subsequent connects do not count towards TimeResumeToReady.
Paul Stewarte4cedde2013-07-17 08:56:44 -0700225 ExpectCommonPostReady(Metrics::kWiFiApModeManaged,
226 Metrics::kWiFiChannel2412,
Thieu Leb84ba342012-03-02 15:15:19 -0800227 Metrics::kWiFiNetworkPhyMode11a,
Paul Stewart23b393a2012-09-25 21:21:06 -0700228 Metrics::kWiFiSecurityWep,
229 -kStrength);
Thieu Leb84ba342012-03-02 15:15:19 -0800230 EXPECT_CALL(library_, SendToUMA("Network.Shill.Wifi.TimeResumeToReady",
231 _, _, _, _)).Times(0);
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700232 metrics_.NotifyServiceStateChanged(wep_wifi_service_,
233 Service::kStateConnected);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000234}
235
Paul Stewart21f40962013-03-01 14:27:28 -0800236TEST_F(MetricsTest, WiFiServicePostReadyEAP) {
237 const int kStrength = -42;
Paul Stewarte4cedde2013-07-17 08:56:44 -0700238 ExpectCommonPostReady(Metrics::kWiFiApModeManaged,
239 Metrics::kWiFiChannel2412,
Paul Stewart21f40962013-03-01 14:27:28 -0800240 Metrics::kWiFiNetworkPhyMode11a,
241 Metrics::kWiFiSecurity8021x,
242 -kStrength);
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700243 eap_wifi_service_->frequency_ = 2412;
244 eap_wifi_service_->physical_mode_ = Metrics::kWiFiNetworkPhyMode11a;
245 eap_wifi_service_->raw_signal_strength_ = kStrength;
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700246 EXPECT_CALL(*eap_, OutputConnectionMetrics(&metrics_, Technology::kWifi));
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700247 metrics_.RegisterService(eap_wifi_service_);
248 metrics_.NotifyServiceStateChanged(eap_wifi_service_,
249 Service::kStateConnected);
Paul Stewart21f40962013-03-01 14:27:28 -0800250}
251
Paul Stewarte4cedde2013-07-17 08:56:44 -0700252TEST_F(MetricsTest, WiFiServicePostReadyAdHoc) {
253 auto adhoc_wifi_service(
254 make_scoped_refptr(new MockWiFiService(&control_interface_,
255 &dispatcher_,
256 &metrics_,
257 &manager_,
258 manager_.wifi_provider(),
259 ssid_,
260 flimflam::kModeAdhoc,
261 flimflam::kSecurityNone,
262 false)));
263 const int kStrength = -42;
264 ExpectCommonPostReady(Metrics::kWiFiApModeAdHoc,
265 Metrics::kWiFiChannel2412,
266 Metrics::kWiFiNetworkPhyMode11b,
267 Metrics::kWiFiSecurityNone,
268 -kStrength);
269 adhoc_wifi_service->frequency_ = 2412;
270 adhoc_wifi_service->physical_mode_ = Metrics::kWiFiNetworkPhyMode11b;
271 adhoc_wifi_service->raw_signal_strength_ = kStrength;
272 metrics_.RegisterService(adhoc_wifi_service);
273 metrics_.NotifyServiceStateChanged(adhoc_wifi_service,
274 Service::kStateConnected);
275}
276
Thieu Le48e6d6d2011-12-06 00:40:27 +0000277TEST_F(MetricsTest, FrequencyToChannel) {
278 EXPECT_EQ(Metrics::kWiFiChannelUndef, metrics_.WiFiFrequencyToChannel(2411));
279 EXPECT_EQ(Metrics::kWiFiChannel2412, metrics_.WiFiFrequencyToChannel(2412));
280 EXPECT_EQ(Metrics::kWiFiChannel2472, metrics_.WiFiFrequencyToChannel(2472));
281 EXPECT_EQ(Metrics::kWiFiChannelUndef, metrics_.WiFiFrequencyToChannel(2473));
282 EXPECT_EQ(Metrics::kWiFiChannel2484, metrics_.WiFiFrequencyToChannel(2484));
283 EXPECT_EQ(Metrics::kWiFiChannelUndef, metrics_.WiFiFrequencyToChannel(5169));
284 EXPECT_EQ(Metrics::kWiFiChannel5170, metrics_.WiFiFrequencyToChannel(5170));
285 EXPECT_EQ(Metrics::kWiFiChannel5190, metrics_.WiFiFrequencyToChannel(5190));
286 EXPECT_EQ(Metrics::kWiFiChannel5180, metrics_.WiFiFrequencyToChannel(5180));
287 EXPECT_EQ(Metrics::kWiFiChannel5200, metrics_.WiFiFrequencyToChannel(5200));
288 EXPECT_EQ(Metrics::kWiFiChannel5230, metrics_.WiFiFrequencyToChannel(5230));
289 EXPECT_EQ(Metrics::kWiFiChannelUndef, metrics_.WiFiFrequencyToChannel(5231));
290 EXPECT_EQ(Metrics::kWiFiChannelUndef, metrics_.WiFiFrequencyToChannel(5239));
291 EXPECT_EQ(Metrics::kWiFiChannel5240, metrics_.WiFiFrequencyToChannel(5240));
292 EXPECT_EQ(Metrics::kWiFiChannelUndef, metrics_.WiFiFrequencyToChannel(5241));
293 EXPECT_EQ(Metrics::kWiFiChannel5320, metrics_.WiFiFrequencyToChannel(5320));
294 EXPECT_EQ(Metrics::kWiFiChannelUndef, metrics_.WiFiFrequencyToChannel(5321));
295 EXPECT_EQ(Metrics::kWiFiChannelUndef, metrics_.WiFiFrequencyToChannel(5499));
296 EXPECT_EQ(Metrics::kWiFiChannel5500, metrics_.WiFiFrequencyToChannel(5500));
297 EXPECT_EQ(Metrics::kWiFiChannelUndef, metrics_.WiFiFrequencyToChannel(5501));
298 EXPECT_EQ(Metrics::kWiFiChannel5700, metrics_.WiFiFrequencyToChannel(5700));
299 EXPECT_EQ(Metrics::kWiFiChannelUndef, metrics_.WiFiFrequencyToChannel(5701));
300 EXPECT_EQ(Metrics::kWiFiChannelUndef, metrics_.WiFiFrequencyToChannel(5744));
301 EXPECT_EQ(Metrics::kWiFiChannel5745, metrics_.WiFiFrequencyToChannel(5745));
302 EXPECT_EQ(Metrics::kWiFiChannelUndef, metrics_.WiFiFrequencyToChannel(5746));
303 EXPECT_EQ(Metrics::kWiFiChannel5825, metrics_.WiFiFrequencyToChannel(5825));
304 EXPECT_EQ(Metrics::kWiFiChannelUndef, metrics_.WiFiFrequencyToChannel(5826));
305}
306
Thieu Lea20cbc22012-01-09 22:01:43 +0000307TEST_F(MetricsTest, TimeOnlineTimeToDrop) {
308 chromeos_metrics::TimerMock *mock_time_online_timer =
309 new chromeos_metrics::TimerMock;
310 metrics_.set_time_online_timer(mock_time_online_timer);
311 chromeos_metrics::TimerMock *mock_time_to_drop_timer =
312 new chromeos_metrics::TimerMock;
313 metrics_.set_time_to_drop_timer(mock_time_to_drop_timer);
314 EXPECT_CALL(*service_.get(), technology()).
315 WillOnce(Return(Technology::kEthernet));
316 EXPECT_CALL(library_, SendToUMA("Network.Shill.Ethernet.TimeOnline",
317 Ge(0),
318 Metrics::kMetricTimeOnlineSecondsMin,
319 Metrics::kMetricTimeOnlineSecondsMax,
320 Metrics::kTimerHistogramNumBuckets));
321 EXPECT_CALL(library_, SendToUMA(Metrics::kMetricTimeToDropSeconds,
322 Ge(0),
323 Metrics::kMetricTimeToDropSecondsMin,
324 Metrics::kMetricTimeToDropSecondsMax,
325 Metrics::kTimerHistogramNumBuckets)).Times(0);
326 EXPECT_CALL(*mock_time_online_timer, Start()).Times(2);
327 EXPECT_CALL(*mock_time_to_drop_timer, Start());
328 metrics_.NotifyDefaultServiceChanged(service_);
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700329 metrics_.NotifyDefaultServiceChanged(open_wifi_service_);
Thieu Lea20cbc22012-01-09 22:01:43 +0000330
331 EXPECT_CALL(*mock_time_online_timer, Start());
332 EXPECT_CALL(*mock_time_to_drop_timer, Start()).Times(0);
333 EXPECT_CALL(library_, SendToUMA("Network.Shill.Wifi.TimeOnline",
334 Ge(0),
335 Metrics::kMetricTimeOnlineSecondsMin,
336 Metrics::kMetricTimeOnlineSecondsMax,
337 Metrics::kTimerHistogramNumBuckets));
338 EXPECT_CALL(library_, SendToUMA(Metrics::kMetricTimeToDropSeconds,
339 Ge(0),
340 Metrics::kMetricTimeToDropSecondsMin,
341 Metrics::kMetricTimeToDropSecondsMax,
342 Metrics::kTimerHistogramNumBuckets));
343 metrics_.NotifyDefaultServiceChanged(NULL);
344}
345
Thieu Le67370f62012-02-14 23:01:42 +0000346TEST_F(MetricsTest, Disconnect) {
347 EXPECT_CALL(*service_.get(), technology()).
348 WillRepeatedly(Return(Technology::kWifi));
349 EXPECT_CALL(*service_.get(), explicitly_disconnected()).
350 WillOnce(Return(false));
351 EXPECT_CALL(library_, SendToUMA("Network.Shill.Wifi.Disconnect",
352 false,
353 Metrics::kMetricDisconnectMin,
354 Metrics::kMetricDisconnectMax,
355 Metrics::kMetricDisconnectNumBuckets));
356 metrics_.NotifyServiceDisconnect(service_);
357
358 EXPECT_CALL(*service_.get(), explicitly_disconnected()).
359 WillOnce(Return(true));
360 EXPECT_CALL(library_, SendToUMA("Network.Shill.Wifi.Disconnect",
361 true,
362 Metrics::kMetricDisconnectMin,
363 Metrics::kMetricDisconnectMax,
364 Metrics::kMetricDisconnectNumBuckets));
365 metrics_.NotifyServiceDisconnect(service_);
366}
367
Thieu Le85e050b2012-03-13 15:04:38 -0700368TEST_F(MetricsTest, PortalDetectionResultToEnum) {
369 PortalDetector::Result result(PortalDetector::kPhaseDNS,
370 PortalDetector::kStatusFailure, 0, true);
371 EXPECT_EQ(Metrics::kPortalResultDNSFailure,
372 Metrics::PortalDetectionResultToEnum(result));
373
374 result.phase = PortalDetector::kPhaseDNS;
375 result.status = PortalDetector::kStatusTimeout;
376 EXPECT_EQ(Metrics::kPortalResultDNSTimeout,
377 Metrics::PortalDetectionResultToEnum(result));
378
379 result.phase = PortalDetector::kPhaseConnection;
380 result.status = PortalDetector::kStatusFailure;
381 EXPECT_EQ(Metrics::kPortalResultConnectionFailure,
382 Metrics::PortalDetectionResultToEnum(result));
383
384 result.phase = PortalDetector::kPhaseConnection;
385 result.status = PortalDetector::kStatusTimeout;
386 EXPECT_EQ(Metrics::kPortalResultConnectionTimeout,
387 Metrics::PortalDetectionResultToEnum(result));
388
389 result.phase = PortalDetector::kPhaseHTTP;
390 result.status = PortalDetector::kStatusFailure;
391 EXPECT_EQ(Metrics::kPortalResultHTTPFailure,
392 Metrics::PortalDetectionResultToEnum(result));
393
394 result.phase = PortalDetector::kPhaseHTTP;
395 result.status = PortalDetector::kStatusTimeout;
396 EXPECT_EQ(Metrics::kPortalResultHTTPTimeout,
397 Metrics::PortalDetectionResultToEnum(result));
398
399 result.phase = PortalDetector::kPhaseContent;
400 result.status = PortalDetector::kStatusSuccess;
401 EXPECT_EQ(Metrics::kPortalResultSuccess,
402 Metrics::PortalDetectionResultToEnum(result));
403
404 result.phase = PortalDetector::kPhaseContent;
405 result.status = PortalDetector::kStatusFailure;
406 EXPECT_EQ(Metrics::kPortalResultContentFailure,
407 Metrics::PortalDetectionResultToEnum(result));
408
409 result.phase = PortalDetector::kPhaseContent;
410 result.status = PortalDetector::kStatusTimeout;
411 EXPECT_EQ(Metrics::kPortalResultContentTimeout,
412 Metrics::PortalDetectionResultToEnum(result));
413
414 result.phase = PortalDetector::kPhaseUnknown;
415 result.status = PortalDetector::kStatusFailure;
416 EXPECT_EQ(Metrics::kPortalResultUnknown,
417 Metrics::PortalDetectionResultToEnum(result));
418}
419
Thieu Lecdb5a212013-01-25 11:17:18 -0800420TEST_F(MetricsTest, TimeToConnect) {
421 EXPECT_CALL(library_,
422 SendToUMA("Network.Shill.Cellular.TimeToConnect",
423 Ge(0),
424 Metrics::kMetricTimeToConnectMillisecondsMin,
425 Metrics::kMetricTimeToConnectMillisecondsMax,
426 Metrics::kMetricTimeToConnectMillisecondsNumBuckets));
427 const int kInterfaceIndex = 1;
428 metrics_.RegisterDevice(kInterfaceIndex, Technology::kCellular);
Thieu Le7cf36b02013-01-30 17:15:56 -0800429 metrics_.NotifyDeviceConnectStarted(kInterfaceIndex, false);
Thieu Lecdb5a212013-01-25 11:17:18 -0800430 metrics_.NotifyDeviceConnectFinished(kInterfaceIndex);
431}
432
Thieu Lea2519bf2013-01-23 16:51:54 -0800433TEST_F(MetricsTest, TimeToDisable) {
434 EXPECT_CALL(library_,
435 SendToUMA("Network.Shill.Cellular.TimeToDisable",
436 Ge(0),
437 Metrics::kMetricTimeToDisableMillisecondsMin,
438 Metrics::kMetricTimeToDisableMillisecondsMax,
439 Metrics::kMetricTimeToDisableMillisecondsNumBuckets));
440 const int kInterfaceIndex = 1;
441 metrics_.RegisterDevice(kInterfaceIndex, Technology::kCellular);
442 metrics_.NotifyDeviceDisableStarted(kInterfaceIndex);
443 metrics_.NotifyDeviceDisableFinished(kInterfaceIndex);
444}
445
Thieu Lece4483e2013-01-23 15:12:03 -0800446TEST_F(MetricsTest, TimeToEnable) {
447 EXPECT_CALL(library_,
448 SendToUMA("Network.Shill.Cellular.TimeToEnable",
449 Ge(0),
450 Metrics::kMetricTimeToEnableMillisecondsMin,
451 Metrics::kMetricTimeToEnableMillisecondsMax,
452 Metrics::kMetricTimeToEnableMillisecondsNumBuckets));
453 const int kInterfaceIndex = 1;
454 metrics_.RegisterDevice(kInterfaceIndex, Technology::kCellular);
455 metrics_.NotifyDeviceEnableStarted(kInterfaceIndex);
456 metrics_.NotifyDeviceEnableFinished(kInterfaceIndex);
457}
458
Thieu Lec8078a62013-01-22 18:01:12 -0800459TEST_F(MetricsTest, TimeToInitialize) {
460 EXPECT_CALL(library_,
461 SendToUMA("Network.Shill.Cellular.TimeToInitialize",
462 Ge(0),
463 Metrics::kMetricTimeToInitializeMillisecondsMin,
464 Metrics::kMetricTimeToInitializeMillisecondsMax,
465 Metrics::kMetricTimeToInitializeMillisecondsNumBuckets));
466 const int kInterfaceIndex = 1;
467 metrics_.RegisterDevice(kInterfaceIndex, Technology::kCellular);
468 metrics_.NotifyDeviceInitialized(kInterfaceIndex);
469}
470
Thieu Le18c11072013-01-28 17:21:37 -0800471TEST_F(MetricsTest, TimeToScan) {
472 EXPECT_CALL(library_,
473 SendToUMA("Network.Shill.Cellular.TimeToScan",
474 Ge(0),
475 Metrics::kMetricTimeToScanMillisecondsMin,
476 Metrics::kMetricTimeToScanMillisecondsMax,
477 Metrics::kMetricTimeToScanMillisecondsNumBuckets));
478 const int kInterfaceIndex = 1;
479 metrics_.RegisterDevice(kInterfaceIndex, Technology::kCellular);
480 metrics_.NotifyDeviceScanStarted(kInterfaceIndex);
481 metrics_.NotifyDeviceScanFinished(kInterfaceIndex);
482}
483
Wade Guthrie44f290d2013-05-28 10:16:25 -0700484TEST_F(MetricsTest, TimeToScanAndConnect) {
485 EXPECT_CALL(library_,
486 SendToUMA("Network.Shill.Wifi.TimeToScan",
487 Ge(0),
488 Metrics::kMetricTimeToScanMillisecondsMin,
489 Metrics::kMetricTimeToScanMillisecondsMax,
490 Metrics::kMetricTimeToScanMillisecondsNumBuckets));
491 const int kInterfaceIndex = 1;
492 metrics_.RegisterDevice(kInterfaceIndex, Technology::kWifi);
493 metrics_.NotifyDeviceScanStarted(kInterfaceIndex);
494 metrics_.NotifyDeviceScanFinished(kInterfaceIndex);
495
496 EXPECT_CALL(library_,
497 SendToUMA("Network.Shill.Wifi.TimeToConnect",
498 Ge(0),
499 Metrics::kMetricTimeToConnectMillisecondsMin,
500 Metrics::kMetricTimeToConnectMillisecondsMax,
501 Metrics::kMetricTimeToConnectMillisecondsNumBuckets));
502 EXPECT_CALL(library_,
503 SendToUMA("Network.Shill.Wifi.TimeToScanAndConnect",
504 Ge(0),
505 Metrics::kMetricTimeToScanMillisecondsMin,
506 Metrics::kMetricTimeToScanMillisecondsMax +
507 Metrics::kMetricTimeToConnectMillisecondsMax,
508 Metrics::kMetricTimeToScanMillisecondsNumBuckets +
509 Metrics::kMetricTimeToConnectMillisecondsNumBuckets));
510 metrics_.NotifyDeviceConnectStarted(kInterfaceIndex, false);
511 metrics_.NotifyDeviceConnectFinished(kInterfaceIndex);
512}
513
514TEST_F(MetricsTest, SpontaneousConnect) {
515 const int kInterfaceIndex = 1;
516 metrics_.RegisterDevice(kInterfaceIndex, Technology::kWifi);
517 EXPECT_CALL(library_,
518 SendToUMA("Network.Shill.Wifi.TimeToConnect",
519 Ge(0),
520 Metrics::kMetricTimeToConnectMillisecondsMin,
521 Metrics::kMetricTimeToConnectMillisecondsMax,
522 Metrics::kMetricTimeToConnectMillisecondsNumBuckets)).Times(0);
523 EXPECT_CALL(library_,
524 SendToUMA("Network.Shill.Wifi.TimeToScanAndConnect",
525 Ge(0),
526 Metrics::kMetricTimeToScanMillisecondsMin,
527 Metrics::kMetricTimeToScanMillisecondsMax +
528 Metrics::kMetricTimeToConnectMillisecondsMax,
529 Metrics::kMetricTimeToScanMillisecondsNumBuckets +
530 Metrics::kMetricTimeToConnectMillisecondsNumBuckets)).
531 Times(0);
532 // This simulates a connection that is not scan-based.
533 metrics_.NotifyDeviceConnectFinished(kInterfaceIndex);
534}
535
536TEST_F(MetricsTest, ResetConnectTimer) {
537 const int kInterfaceIndex = 1;
538 metrics_.RegisterDevice(kInterfaceIndex, Technology::kWifi);
539 chromeos_metrics::TimerReporterMock *mock_scan_timer =
540 new chromeos_metrics::TimerReporterMock;
541 metrics_.set_time_to_scan_timer(kInterfaceIndex, mock_scan_timer);
542 chromeos_metrics::TimerReporterMock *mock_connect_timer =
543 new chromeos_metrics::TimerReporterMock;
544 metrics_.set_time_to_connect_timer(kInterfaceIndex, mock_connect_timer);
545 chromeos_metrics::TimerReporterMock *mock_scan_connect_timer =
546 new chromeos_metrics::TimerReporterMock;
547 metrics_.set_time_to_scan_connect_timer(kInterfaceIndex,
548 mock_scan_connect_timer);
549 EXPECT_CALL(*mock_scan_timer, Reset()).Times(0);
550 EXPECT_CALL(*mock_connect_timer, Reset());
551 EXPECT_CALL(*mock_scan_connect_timer, Reset());
552 metrics_.ResetConnectTimer(kInterfaceIndex);
553}
554
Wade Guthrie091c41c2013-03-22 15:48:53 -0700555TEST_F(MetricsTest, TimeToScanNoStart) {
556 EXPECT_CALL(library_,
557 SendToUMA("Network.Shill.Cellular.TimeToScan", _, _, _, _)).Times(0);
558 const int kInterfaceIndex = 1;
559 metrics_.RegisterDevice(kInterfaceIndex, Technology::kCellular);
560 metrics_.NotifyDeviceScanFinished(kInterfaceIndex);
561}
562
Thieu Le18c11072013-01-28 17:21:37 -0800563TEST_F(MetricsTest, TimeToScanIgnore) {
564 // Make sure TimeToScan is not sent if the elapsed time exceeds the max
565 // value. This simulates the case where the device is in an area with no
566 // service.
567 const int kInterfaceIndex = 1;
568 metrics_.RegisterDevice(kInterfaceIndex, Technology::kCellular);
569 base::TimeDelta large_time_delta =
570 base::TimeDelta::FromMilliseconds(
571 Metrics::kMetricTimeToScanMillisecondsMax + 1);
572 chromeos_metrics::TimerReporterMock *mock_time_to_scan_timer =
573 new chromeos_metrics::TimerReporterMock;
574 metrics_.set_time_to_scan_timer(kInterfaceIndex, mock_time_to_scan_timer);
Wade Guthrie091c41c2013-03-22 15:48:53 -0700575 EXPECT_CALL(*mock_time_to_scan_timer, Stop()).WillOnce(Return(true));
Thieu Le18c11072013-01-28 17:21:37 -0800576 EXPECT_CALL(*mock_time_to_scan_timer, GetElapsedTime(_)).
577 WillOnce(DoAll(SetArgumentPointee<0>(large_time_delta), Return(true)));
578 EXPECT_CALL(library_, SendToUMA(_, _, _, _, _)).Times(0);
579 metrics_.NotifyDeviceScanStarted(kInterfaceIndex);
580 metrics_.NotifyDeviceScanFinished(kInterfaceIndex);
581}
582
Prathmesh Prabhu08757aa2013-05-15 17:17:33 -0700583TEST_F(MetricsTest, Cellular3GPPRegistrationDelayedDropPosted) {
584 EXPECT_CALL(library_,
585 SendEnumToUMA(Metrics::kMetricCellular3GPPRegistrationDelayedDrop,
586 Metrics::kCellular3GPPRegistrationDelayedDropPosted,
587 Metrics::kCellular3GPPRegistrationDelayedDropMax));
588 metrics_.Notify3GPPRegistrationDelayedDropPosted();
589 Mock::VerifyAndClearExpectations(&library_);
590
591 EXPECT_CALL(library_,
592 SendEnumToUMA(Metrics::kMetricCellular3GPPRegistrationDelayedDrop,
593 Metrics::kCellular3GPPRegistrationDelayedDropCanceled,
594 Metrics::kCellular3GPPRegistrationDelayedDropMax));
595 metrics_.Notify3GPPRegistrationDelayedDropCanceled();
596}
597
Thieu Le7cf36b02013-01-30 17:15:56 -0800598TEST_F(MetricsTest, CellularAutoConnect) {
599 EXPECT_CALL(library_,
600 SendToUMA("Network.Shill.Cellular.TimeToConnect",
601 Ge(0),
602 Metrics::kMetricTimeToConnectMillisecondsMin,
603 Metrics::kMetricTimeToConnectMillisecondsMax,
604 Metrics::kMetricTimeToConnectMillisecondsNumBuckets));
605 EXPECT_CALL(library_,
606 SendToUMA(Metrics::kMetricCellularAutoConnectTotalTime,
607 Ge(0),
608 Metrics::kMetricCellularAutoConnectTotalTimeMin,
609 Metrics::kMetricCellularAutoConnectTotalTimeMax,
610 Metrics::kMetricCellularAutoConnectTotalTimeNumBuckets));
611 EXPECT_CALL(library_,
612 SendToUMA(Metrics::kMetricCellularAutoConnectTries,
613 2,
614 Metrics::kMetricCellularAutoConnectTriesMin,
615 Metrics::kMetricCellularAutoConnectTriesMax,
616 Metrics::kMetricCellularAutoConnectTriesNumBuckets));
617 const int kInterfaceIndex = 1;
618 metrics_.RegisterDevice(kInterfaceIndex, Technology::kCellular);
619 metrics_.NotifyDeviceConnectStarted(kInterfaceIndex, true);
620 metrics_.NotifyDeviceConnectStarted(kInterfaceIndex, true);
621 metrics_.NotifyDeviceConnectFinished(kInterfaceIndex);
622}
623
Thieu Le26fc01b2013-01-28 12:08:48 -0800624TEST_F(MetricsTest, CellularDrop) {
625 const char *kUMATechnologyStrings[] = {
626 flimflam::kNetworkTechnology1Xrtt,
627 flimflam::kNetworkTechnologyEdge,
628 flimflam::kNetworkTechnologyEvdo,
629 flimflam::kNetworkTechnologyGprs,
630 flimflam::kNetworkTechnologyGsm,
631 flimflam::kNetworkTechnologyHspa,
632 flimflam::kNetworkTechnologyHspaPlus,
633 flimflam::kNetworkTechnologyLte,
634 flimflam::kNetworkTechnologyUmts,
635 "Unknown" };
636
637 const uint16 signal_strength = 100;
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800638 const int kInterfaceIndex = 1;
639 metrics_.RegisterDevice(kInterfaceIndex, Technology::kCellular);
Thieu Le26fc01b2013-01-28 12:08:48 -0800640 for (size_t index = 0; index < arraysize(kUMATechnologyStrings); ++index) {
641 EXPECT_CALL(library_,
642 SendEnumToUMA(Metrics::kMetricCellularDrop,
643 index,
644 Metrics::kCellularDropTechnologyMax));
645 EXPECT_CALL(library_,
646 SendToUMA(Metrics::kMetricCellularSignalStrengthBeforeDrop,
647 signal_strength,
648 Metrics::kMetricCellularSignalStrengthBeforeDropMin,
649 Metrics::kMetricCellularSignalStrengthBeforeDropMax,
650 Metrics::kMetricCellularSignalStrengthBeforeDropNumBuckets));
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800651 metrics_.NotifyCellularDeviceDrop(kInterfaceIndex,
652 kUMATechnologyStrings[index],
Thieu Le26fc01b2013-01-28 12:08:48 -0800653 signal_strength);
654 Mock::VerifyAndClearExpectations(&library_);
655 }
656}
657
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800658TEST_F(MetricsTest, CellularDropsPerHour) {
659 const int kInterfaceIndex = 1;
660 const int kSignalStrength = 33;
661 const int kNumDrops = 3;
662 metrics_.RegisterDevice(kInterfaceIndex, Technology::kCellular);
663 EXPECT_CALL(library_,
664 SendEnumToUMA(Metrics::kMetricCellularDrop,
665 Metrics::kCellularDropTechnologyLte,
666 Metrics::kCellularDropTechnologyMax))
667 .Times(kNumDrops);
668 EXPECT_CALL(library_,
669 SendToUMA(Metrics::kMetricCellularSignalStrengthBeforeDrop,
670 kSignalStrength,
671 Metrics::kMetricCellularSignalStrengthBeforeDropMin,
672 Metrics::kMetricCellularSignalStrengthBeforeDropMax,
673 Metrics::kMetricCellularSignalStrengthBeforeDropNumBuckets))
674 .Times(kNumDrops);
675 EXPECT_CALL(library_,
676 SendToUMA(Metrics::kMetricCellularDropsPerHour,
677 kNumDrops,
678 Metrics::kMetricCellularDropsPerHourMin,
679 Metrics::kMetricCellularDropsPerHourMax,
680 Metrics::kMetricCellularDropsPerHourNumBuckets));
681 for (int count = 0; count < kNumDrops; ++count)
682 metrics_.NotifyCellularDeviceDrop(kInterfaceIndex,
683 flimflam::kNetworkTechnologyLte,
684 kSignalStrength);
685 metrics_.HourlyTimeoutHandler();
686
687 // Make sure the number of drops gets resetted after each hour.
688 EXPECT_CALL(library_,
689 SendToUMA(Metrics::kMetricCellularDropsPerHour, _, _, _, _))
690 .Times(0);
691 metrics_.HourlyTimeoutHandler();
692}
693
Thieu Leb7aa5f72013-01-31 15:57:48 -0800694TEST_F(MetricsTest, CellularDeviceFailure) {
695 const char kErrorMessage[] =
696 "org.chromium.flimflam.Error.Failure:"
697 "$NWQMISTATUS: QMI_RESULT_FAILURE:QMI_ERR_CALL_FAILED#015#012#011"
698 "QMI State: DISCONNECTED#015#012#011Call End Reason:1016#015#012#011"
699 "Call Duration: 0 seconds#015#015#012"
700 "$NWQMISTATUS: QMI_RESULT_SUCCESS:QMI_ERR_NONE#015#012#011"
701 "QMI State: DISCONNECTED#015#012#011Call End Reason:0#015#012#011"
702 "Call Duration: 0 seconds";
703 string expected_message =
704 string(Metrics::kMetricCellularFailureReason) + kErrorMessage;
705 EXPECT_CALL(library_, SendUserActionToUMA(expected_message));
706 Error error(Error::kOperationFailed, kErrorMessage);
707 metrics_.NotifyCellularDeviceFailure(error);
708}
709
Thieu Le91fccf62013-04-22 15:23:16 -0700710TEST_F(MetricsTest, CellularOutOfCreditsReason) {
711 EXPECT_CALL(library_,
712 SendEnumToUMA(Metrics::kMetricCellularOutOfCreditsReason,
713 Metrics::kCellularOutOfCreditsReasonConnectDisconnectLoop,
714 Metrics::kCellularOutOfCreditsReasonMax));
715 metrics_.NotifyCellularOutOfCredits(
716 Metrics::kCellularOutOfCreditsReasonConnectDisconnectLoop);
717 Mock::VerifyAndClearExpectations(&library_);
718
719 EXPECT_CALL(library_,
720 SendEnumToUMA(Metrics::kMetricCellularOutOfCreditsReason,
721 Metrics::kCellularOutOfCreditsReasonTxCongested,
722 Metrics::kCellularOutOfCreditsReasonMax));
723 metrics_.NotifyCellularOutOfCredits(
724 Metrics::kCellularOutOfCreditsReasonTxCongested);
725 Mock::VerifyAndClearExpectations(&library_);
726
727 EXPECT_CALL(library_,
728 SendEnumToUMA(Metrics::kMetricCellularOutOfCreditsReason,
729 Metrics::kCellularOutOfCreditsReasonElongatedTimeWait,
730 Metrics::kCellularOutOfCreditsReasonMax));
731 metrics_.NotifyCellularOutOfCredits(
732 Metrics::kCellularOutOfCreditsReasonElongatedTimeWait);
733}
734
Thieu Le5133b712013-02-19 14:47:21 -0800735TEST_F(MetricsTest, CorruptedProfile) {
736 EXPECT_CALL(library_, SendEnumToUMA(Metrics::kMetricCorruptedProfile,
737 Metrics::kCorruptedProfile,
738 Metrics::kCorruptedProfileMax));
739 metrics_.NotifyCorruptedProfile();
740}
741
Thieu Le85e050b2012-03-13 15:04:38 -0700742#ifndef NDEBUG
743
744typedef MetricsTest MetricsDeathTest;
745
746TEST_F(MetricsDeathTest, PortalDetectionResultToEnumDNSSuccess) {
747 PortalDetector::Result result(PortalDetector::kPhaseDNS,
748 PortalDetector::kStatusSuccess, 0, true);
749 EXPECT_DEATH(Metrics::PortalDetectionResultToEnum(result),
750 "Final result status 1 is not allowed in the DNS phase");
751}
752
753TEST_F(MetricsDeathTest, PortalDetectionResultToEnumConnectionSuccess) {
754 PortalDetector::Result result(PortalDetector::kPhaseConnection,
755 PortalDetector::kStatusSuccess, 0, true);
756 EXPECT_DEATH(Metrics::PortalDetectionResultToEnum(result),
757 "Final result status 1 is not allowed in the Connection phase");
758}
759
760TEST_F(MetricsDeathTest, PortalDetectionResultToEnumHTTPSuccess) {
761 PortalDetector::Result result(PortalDetector::kPhaseHTTP,
762 PortalDetector::kStatusSuccess, 0, true);
763 EXPECT_DEATH(Metrics::PortalDetectionResultToEnum(result),
764 "Final result status 1 is not allowed in the HTTP phase");
765}
766
767#endif // NDEBUG
768
Thieu Le48e6d6d2011-12-06 00:40:27 +0000769} // namespace shill