14615e0d5aa416ab1a8596bde68f71f7ebe431b86Vitaly Buka// Copyright 2015 The Weave Authors. All rights reserved.
211b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka// Use of this source code is governed by a BSD-style license that can be
311b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka// found in the LICENSE file.
411b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
511b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka#include <weave/device.h>
611b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
711b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka#include <gmock/gmock.h>
811b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka#include <gtest/gtest.h>
9727f3e675fece0ebdcdb0bf0aaf083c374d64d95Vitaly Buka#include <weave/provider/test/fake_task_runner.h>
101e3636732171afb8cceb9e5cb835ec6a93787dbaVitaly Buka#include <weave/provider/test/mock_bluetooth.h>
111e3636732171afb8cceb9e5cb835ec6a93787dbaVitaly Buka#include <weave/provider/test/mock_config_store.h>
121e3636732171afb8cceb9e5cb835ec6a93787dbaVitaly Buka#include <weave/provider/test/mock_dns_service_discovery.h>
131e3636732171afb8cceb9e5cb835ec6a93787dbaVitaly Buka#include <weave/provider/test/mock_http_client.h>
141e3636732171afb8cceb9e5cb835ec6a93787dbaVitaly Buka#include <weave/provider/test/mock_http_server.h>
151e3636732171afb8cceb9e5cb835ec6a93787dbaVitaly Buka#include <weave/provider/test/mock_network.h>
161e3636732171afb8cceb9e5cb835ec6a93787dbaVitaly Buka#include <weave/provider/test/mock_wifi.h>
17ef213d7f63585accbb7ac9bd5112aeeb1b593c9dVitaly Buka#include <weave/test/mock_command.h>
18a8ece8f8534ca9b551f93bdba2982f40aff3d619Vitaly Buka#include <weave/test/mock_device.h>
190f6b2eccc9ca4aa35cf0ee1e3ac7bc6edc38f0a4Vitaly Buka#include <weave/test/unittest_utils.h>
2011b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
212d16dfa768282b29f3fd5a905b52e3393a083e0dStefan Sauer#include "src/bind_lambda.h"
2211b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
2311b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Bukausing testing::_;
2465e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Bukausing testing::AtLeast;
2511b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Bukausing testing::AtMost;
2611b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Bukausing testing::HasSubstr;
2765e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Bukausing testing::InSequence;
2811b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Bukausing testing::Invoke;
2911b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Bukausing testing::InvokeWithoutArgs;
3011b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Bukausing testing::MatchesRegex;
3111b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Bukausing testing::Mock;
3211b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Bukausing testing::Return;
3311b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Bukausing testing::ReturnRefOfCopy;
3411b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Bukausing testing::StartsWith;
3511b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Bukausing testing::StrictMock;
3611b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Bukausing testing::WithArgs;
3711b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
3811b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Bukanamespace weave {
3911b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
40e69e4ee64c466730b98fb7fa3049aabcc85f8984Vitaly Bukanamespace {
41e69e4ee64c466730b98fb7fa3049aabcc85f8984Vitaly Buka
421a42e1466de3edd0c79215b739cd8e929ef8a7e8Vitaly Bukausing provider::HttpClient;
431a42e1466de3edd0c79215b739cd8e929ef8a7e8Vitaly Bukausing provider::Network;
441a42e1466de3edd0c79215b739cd8e929ef8a7e8Vitaly Bukausing provider::test::MockHttpClientResponse;
450f6b2eccc9ca4aa35cf0ee1e3ac7bc6edc38f0a4Vitaly Bukausing test::CreateDictionaryValue;
460f6b2eccc9ca4aa35cf0ee1e3ac7bc6edc38f0a4Vitaly Bukausing test::ValueToString;
4711b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
48551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenkoconst char kTraitDefs[] = R"({
49551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko  "trait1": {
50551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko    "commands": {
51551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko      "reboot": {
52551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko        "minimalRole": "user"
53551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko      },
54551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko      "shutdown": {
55551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko        "minimalRole": "user",
56551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko        "parameters": {},
57551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko        "results": {}
58551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko      }
592c7740aac024de03aafcf09ee69f157384d44038Alex Vakulenko    },
60551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko    "state": {
61551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko      "firmwareVersion": {"type": "string"}
62551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko    }
63551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko  },
64551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko  "trait2": {
65551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko    "state": {
66551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko      "battery_level": {"type": "integer"}
6711b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka    }
6811b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  }
6911b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka})";
7011b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
7111b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Bukaconst char kDeviceResource[] = R"({
7288272d5b9e88dfd253c18aea4792fe57ee51696dVitaly Buka  "kind": "weave#device",
730b7bb9f1484126e098d0c2a295d4213583005b19Johan Euphrosine  "id": "CLOUD_ID",
7411b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  "channel": {
7511b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka    "supportedType": "pull"
7611b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  },
7711b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  "deviceKind": "vendor",
7811b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  "modelManifestId": "ABCDE",
7911b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  "systemName": "",
80a05eadb5a34b90e3aec184c41b9e3481e18902b3Vitaly Buka  "name": "TEST_NAME",
8111b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  "displayName": "",
8211b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  "description": "Developer device",
8311b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  "stateValidationEnabled": true,
8411b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  "commandDefs":{
85551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko    "trait1": {
8611b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka      "reboot": {
8711b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka        "minimalRole": "user",
887e894da1c5fcc4fafa6cc69b612c9c14f78aed51Alex Vakulenko        "parameters": {"delay": {"type": "integer"}},
8911b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka        "results": {}
9011b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka      },
9111b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka      "shutdown": {
9211b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka        "minimalRole": "user",
9311b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka        "parameters": {},
9411b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka        "results": {}
9511b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka      }
9611b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka    }
9711b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  },
9811b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  "state":{
99551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko    "trait1": {"firmwareVersion":"FIRMWARE_VERSION"},
100551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko    "trait2": {"battery_level":44}
101551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko  },
102551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko  "traits": {
103551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko    "trait1": {
104551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko      "commands": {
105551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko        "reboot": {
106551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko          "minimalRole": "user"
107551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko        },
108551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko        "shutdown": {
109551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko          "minimalRole": "user",
110551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko          "parameters": {},
111551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko          "results": {}
112551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko        }
113551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko      },
114551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko      "state": {
115551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko        "firmwareVersion": {"type": "string"}
11611b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka      }
11711b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka    },
118551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko    "trait2": {
119551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko      "state": {
120551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko        "battery_level": {"type": "integer"}
121551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko      }
122551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko    }
123551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko  },
124551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko  "components": {
125551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko    "myComponent": {
126551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko      "traits": ["trait1", "trait2"],
127551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko      "state": {
128551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko        "trait1": {"firmwareVersion":"FIRMWARE_VERSION"},
129551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko        "trait2": {"battery_level":44}
130551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko      }
131551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko    }
13211b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  }
13311b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka})";
13411b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
13511b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Bukaconst char kRegistrationResponse[] = R"({
13688272d5b9e88dfd253c18aea4792fe57ee51696dVitaly Buka  "kind": "weave#registrationTicket",
1370b7bb9f1484126e098d0c2a295d4213583005b19Johan Euphrosine  "id": "TICKET_ID",
1380b7bb9f1484126e098d0c2a295d4213583005b19Johan Euphrosine  "deviceId": "CLOUD_ID",
13911b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  "oauthClientId": "CLIENT_ID",
14011b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  "userEmail": "USER@gmail.com",
14111b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  "creationTimeMs": "1440087183738",
14211b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  "expirationTimeMs": "1440087423738"
14311b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka})";
14411b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
14511b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Bukaconst char kRegistrationFinalResponse[] = R"({
14688272d5b9e88dfd253c18aea4792fe57ee51696dVitaly Buka  "kind": "weave#registrationTicket",
1470b7bb9f1484126e098d0c2a295d4213583005b19Johan Euphrosine  "id": "TICKET_ID",
1480b7bb9f1484126e098d0c2a295d4213583005b19Johan Euphrosine  "deviceId": "CLOUD_ID",
14911b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  "oauthClientId": "CLIENT_ID",
15011b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  "userEmail": "USER@gmail.com",
15111b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  "robotAccountEmail": "ROBO@gmail.com",
15211b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  "robotAccountAuthorizationCode": "AUTH_CODE",
15311b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  "creationTimeMs": "1440087183738",
15411b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  "expirationTimeMs": "1440087423738"
15511b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka})";
15611b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
15711b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Bukaconst char kAuthTokenResponse[] = R"({
15811b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  "access_token" : "ACCESS_TOKEN",
15911b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  "token_type" : "Bearer",
16011b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  "expires_in" : 3599,
16111b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  "refresh_token" : "REFRESH_TOKEN"
16211b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka})";
16311b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
1643dc2f53ffba89aa380a0474205b57681537b6159Vitaly BukaMATCHER_P(MatchTxt, txt, "") {
1653dc2f53ffba89aa380a0474205b57681537b6159Vitaly Buka  std::vector<std::string> txt_copy = txt;
1663dc2f53ffba89aa380a0474205b57681537b6159Vitaly Buka  std::sort(txt_copy.begin(), txt_copy.end());
1673dc2f53ffba89aa380a0474205b57681537b6159Vitaly Buka  std::vector<std::string> arg_copy = arg;
1683dc2f53ffba89aa380a0474205b57681537b6159Vitaly Buka  std::sort(arg_copy.begin(), arg_copy.end());
1693dc2f53ffba89aa380a0474205b57681537b6159Vitaly Buka  return (arg_copy == txt_copy);
1703dc2f53ffba89aa380a0474205b57681537b6159Vitaly Buka}
1713dc2f53ffba89aa380a0474205b57681537b6159Vitaly Buka
172e69e4ee64c466730b98fb7fa3049aabcc85f8984Vitaly Bukatemplate <class Map>
173e69e4ee64c466730b98fb7fa3049aabcc85f8984Vitaly Bukastd::set<typename Map::key_type> GetKeys(const Map& map) {
174e69e4ee64c466730b98fb7fa3049aabcc85f8984Vitaly Buka  std::set<typename Map::key_type> result;
175e69e4ee64c466730b98fb7fa3049aabcc85f8984Vitaly Buka  for (const auto& pair : map)
176e69e4ee64c466730b98fb7fa3049aabcc85f8984Vitaly Buka    result.insert(pair.first);
177e69e4ee64c466730b98fb7fa3049aabcc85f8984Vitaly Buka  return result;
178e69e4ee64c466730b98fb7fa3049aabcc85f8984Vitaly Buka}
179e69e4ee64c466730b98fb7fa3049aabcc85f8984Vitaly Buka
180e69e4ee64c466730b98fb7fa3049aabcc85f8984Vitaly Buka}  // namespace
181e69e4ee64c466730b98fb7fa3049aabcc85f8984Vitaly Buka
18211b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Bukaclass WeaveTest : public ::testing::Test {
18311b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka protected:
1846a1ba84d9b295dcc0c8f50b580182a665c4aa8ceVitaly Buka  void SetUp() override {
1856a1ba84d9b295dcc0c8f50b580182a665c4aa8ceVitaly Buka    EXPECT_CALL(wifi_, IsWifi24Supported()).WillRepeatedly(Return(true));
1866a1ba84d9b295dcc0c8f50b580182a665c4aa8ceVitaly Buka    EXPECT_CALL(wifi_, IsWifi50Supported()).WillRepeatedly(Return(false));
1876a1ba84d9b295dcc0c8f50b580182a665c4aa8ceVitaly Buka  }
18811b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
18972d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka  template <class UrlMatcher>
1901a42e1466de3edd0c79215b739cd8e929ef8a7e8Vitaly Buka  void ExpectRequest(HttpClient::Method method,
19172d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka                     const UrlMatcher& url_matcher,
19211b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka                     const std::string& json_response) {
19372d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka    EXPECT_CALL(http_client_, SendRequest(method, url_matcher, _, _, _))
19434668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka        .WillOnce(WithArgs<4>(Invoke(
19534668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            [json_response](const HttpClient::SendRequestCallback& callback) {
19634668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka              std::unique_ptr<provider::test::MockHttpClientResponse> response{
19734668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                  new StrictMock<provider::test::MockHttpClientResponse>};
19834668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka              EXPECT_CALL(*response, GetStatusCode())
19934668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                  .Times(AtLeast(1))
20034668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                  .WillRepeatedly(Return(200));
20134668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka              EXPECT_CALL(*response, GetContentType())
20234668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                  .Times(AtLeast(1))
20334668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                  .WillRepeatedly(Return("application/json; charset=utf-8"));
20434668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka              EXPECT_CALL(*response, GetData())
20534668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                  .WillRepeatedly(Return(json_response));
20634668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka              callback.Run(std::move(response), nullptr);
20734668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka            })));
20811b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  }
20911b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
21011b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  void InitNetwork() {
2113ab6f6e82d3feda765336c3ddd5cfbb8187f17f5Vitaly Buka    EXPECT_CALL(network_, AddConnectionChangedCallback(_))
2123ab6f6e82d3feda765336c3ddd5cfbb8187f17f5Vitaly Buka        .WillRepeatedly(Invoke(
2131e3636732171afb8cceb9e5cb835ec6a93787dbaVitaly Buka            [this](const provider::Network::ConnectionChangedCallback& cb) {
214ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka              network_callbacks_.push_back(cb);
215ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka            }));
21611b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka    EXPECT_CALL(network_, GetConnectionState())
21735f317dacc5176ccc8a7b2b80eeb518ed1f632cdVitaly Buka        .WillRepeatedly(Return(Network::State::kOffline));
218ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka  }
219ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka
220beddc6023ef95fdf2c45ad9a300411a2b3895692Vitaly Buka  void InitDnsSd() {
221beddc6023ef95fdf2c45ad9a300411a2b3895692Vitaly Buka    EXPECT_CALL(dns_sd_, PublishService(_, _, _)).WillRepeatedly(Return());
222beddc6023ef95fdf2c45ad9a300411a2b3895692Vitaly Buka    EXPECT_CALL(dns_sd_, StopPublishing("_privet._tcp")).WillOnce(Return());
22311b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  }
22411b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
225beddc6023ef95fdf2c45ad9a300411a2b3895692Vitaly Buka  void InitDnsSdPublishing(bool registered, const std::string& flags) {
22687eb78898cd2e8e632ed1a6eac641bd3bd1435a9Vitaly Buka    std::vector<std::string> txt{
22787eb78898cd2e8e632ed1a6eac641bd3bd1435a9Vitaly Buka        {"id=TEST_DEVICE_ID"},         {"flags=" + flags}, {"mmid=ABCDE"},
22887eb78898cd2e8e632ed1a6eac641bd3bd1435a9Vitaly Buka        {"services=developmentBoard"}, {"txtvers=3"},      {"ty=TEST_NAME"}};
22911b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka    if (registered) {
2300b7bb9f1484126e098d0c2a295d4213583005b19Johan Euphrosine      txt.push_back("gcd_id=CLOUD_ID");
23111b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
23211b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka      // During registration device may announce itself twice:
23311b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka      // 1. with GCD ID but not connected (DB)
23411b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka      // 2. with GCD ID and connected (BB)
235beddc6023ef95fdf2c45ad9a300411a2b3895692Vitaly Buka      EXPECT_CALL(dns_sd_, PublishService("_privet._tcp", 11, MatchTxt(txt)))
23611b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka          .Times(AtMost(1))
23711b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka          .WillOnce(Return());
23811b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
2393dc2f53ffba89aa380a0474205b57681537b6159Vitaly Buka      txt[1] = "flags=BB";
24011b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka    }
24111b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
242beddc6023ef95fdf2c45ad9a300411a2b3895692Vitaly Buka    EXPECT_CALL(dns_sd_, PublishService("_privet._tcp", 11, MatchTxt(txt)))
243bced5affdc79322da2ac334463e0aa0cf5fe0649Vitaly Buka        .Times(AtMost(1))
2443dc2f53ffba89aa380a0474205b57681537b6159Vitaly Buka        .WillOnce(Return());
24511b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  }
24611b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
24711b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  void InitHttpServer() {
24811b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka    EXPECT_CALL(http_server_, GetHttpPort()).WillRepeatedly(Return(11));
24911b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka    EXPECT_CALL(http_server_, GetHttpsPort()).WillRepeatedly(Return(12));
250efee3a281cddd7975d4f732bf8179b1e32ce6806Alex Vakulenko    EXPECT_CALL(http_server_, GetRequestTimeout())
251efee3a281cddd7975d4f732bf8179b1e32ce6806Alex Vakulenko        .WillRepeatedly(Return(base::TimeDelta::Max()));
25211b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka    EXPECT_CALL(http_server_, GetHttpsCertificateFingerprint())
253138aec4d9486974563a63903f2a74b7a797c2aeeVitaly Buka        .WillRepeatedly(Return(std::vector<uint8_t>{1, 2, 3}));
2541a39c81c169e677601ddf67ad0a443ca6226033cVitaly Buka    EXPECT_CALL(http_server_, AddHttpRequestHandler(_, _))
2551a39c81c169e677601ddf67ad0a443ca6226033cVitaly Buka        .WillRepeatedly(Invoke(
2561a39c81c169e677601ddf67ad0a443ca6226033cVitaly Buka            [this](const std::string& path_prefix,
2571a39c81c169e677601ddf67ad0a443ca6226033cVitaly Buka                   const provider::HttpServer::RequestHandlerCallback& cb) {
258e69e4ee64c466730b98fb7fa3049aabcc85f8984Vitaly Buka              http_handlers_[path_prefix] = cb;
2591a39c81c169e677601ddf67ad0a443ca6226033cVitaly Buka            }));
2601a39c81c169e677601ddf67ad0a443ca6226033cVitaly Buka    EXPECT_CALL(http_server_, AddHttpsRequestHandler(_, _))
26101893cc3989f53fd9832e8aa7029039ebd2d2877Vitaly Buka        .WillRepeatedly(Invoke(
26201893cc3989f53fd9832e8aa7029039ebd2d2877Vitaly Buka            [this](const std::string& path_prefix,
26301893cc3989f53fd9832e8aa7029039ebd2d2877Vitaly Buka                   const provider::HttpServer::RequestHandlerCallback& cb) {
264e69e4ee64c466730b98fb7fa3049aabcc85f8984Vitaly Buka              https_handlers_[path_prefix] = cb;
2651e3636732171afb8cceb9e5cb835ec6a93787dbaVitaly Buka            }));
26611b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  }
26711b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
268ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka  void InitDefaultExpectations() {
26911b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka    InitNetwork();
270a05eadb5a34b90e3aec184c41b9e3481e18902b3Vitaly Buka    EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
271ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka        .WillOnce(Return());
27211b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka    InitHttpServer();
273beddc6023ef95fdf2c45ad9a300411a2b3895692Vitaly Buka    InitDnsSd();
274ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka  }
27511b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
276ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka  void StartDevice() {
277c5bdd173a217503710bf1d700a03bfe9a614bb4aVitaly Buka    device_ = weave::Device::Create(&config_store_, &task_runner_,
278c5bdd173a217503710bf1d700a03bfe9a614bb4aVitaly Buka                                    &http_client_, &network_, &dns_sd_,
279c5bdd173a217503710bf1d700a03bfe9a614bb4aVitaly Buka                                    &http_server_, &wifi_, &bluetooth_);
28011b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
281e69e4ee64c466730b98fb7fa3049aabcc85f8984Vitaly Buka    EXPECT_EQ((std::set<std::string>{
28234668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                  // clang-format off
28334668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                  "/privet/info",
28434668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                  "/privet/v3/pairing/cancel",
28534668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                  "/privet/v3/pairing/confirm",
28634668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                  "/privet/v3/pairing/start",
28734668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                  // clang-format on
28834668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka              }),
289e69e4ee64c466730b98fb7fa3049aabcc85f8984Vitaly Buka              GetKeys(http_handlers_));
290e69e4ee64c466730b98fb7fa3049aabcc85f8984Vitaly Buka    EXPECT_EQ((std::set<std::string>{
29134668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                  // clang-format off
29234668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                  "/privet/info",
2932d24e0ea050085e91bb8282a0408561d6a17797aVitaly Buka                  "/privet/v3/accessControl/claim",
2942d24e0ea050085e91bb8282a0408561d6a17797aVitaly Buka                  "/privet/v3/accessControl/confirm",
29534668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                  "/privet/v3/auth",
29634668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                  "/privet/v3/checkForUpdates",
29734668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                  "/privet/v3/commandDefs",
29834668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                  "/privet/v3/commands/cancel",
29934668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                  "/privet/v3/commands/execute",
30034668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                  "/privet/v3/commands/list",
30134668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                  "/privet/v3/commands/status",
30234668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                  "/privet/v3/components",
30334668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                  "/privet/v3/pairing/cancel",
30434668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                  "/privet/v3/pairing/confirm",
30534668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                  "/privet/v3/pairing/start",
30634668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                  "/privet/v3/setup/start",
30734668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                  "/privet/v3/setup/status",
30834668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                  "/privet/v3/state",
30934668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                  "/privet/v3/traits",
31034668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka                  // clang-format on
31134668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka              }),
312e69e4ee64c466730b98fb7fa3049aabcc85f8984Vitaly Buka              GetKeys(https_handlers_));
313e69e4ee64c466730b98fb7fa3049aabcc85f8984Vitaly Buka
314551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko    device_->AddTraitDefinitionsFromJson(kTraitDefs);
31534668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka    EXPECT_TRUE(
31634668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka        device_->AddComponent("myComponent", {"trait1", "trait2"}, nullptr));
317551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko    EXPECT_TRUE(device_->SetStatePropertiesFromJson(
318551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko        "myComponent", R"({"trait2": {"battery_level":44}})", nullptr));
3190ac6ca687c519367158c6be76c5b7bff2064bac4Vitaly Buka
32011b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka    task_runner_.Run();
32111b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  }
32211b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
32335f317dacc5176ccc8a7b2b80eeb518ed1f632cdVitaly Buka  void NotifyNetworkChanged(provider::Network::State state,
3241e3636732171afb8cceb9e5cb835ec6a93787dbaVitaly Buka                            base::TimeDelta delay) {
32565e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka    auto task = [this, state] {
32665e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka      EXPECT_CALL(network_, GetConnectionState()).WillRepeatedly(Return(state));
32765e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka      for (const auto& cb : network_callbacks_)
32865e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka        cb.Run();
32965e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka    };
33065e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka
33165e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka    task_runner_.PostDelayedTask(FROM_HERE, base::Bind(task), delay);
3323884ce15b28039b7c73cf2e79a4c060ca3701bf3Vitaly Buka  }
3333884ce15b28039b7c73cf2e79a4c060ca3701bf3Vitaly Buka
334e69e4ee64c466730b98fb7fa3049aabcc85f8984Vitaly Buka  std::map<std::string, provider::HttpServer::RequestHandlerCallback>
335e69e4ee64c466730b98fb7fa3049aabcc85f8984Vitaly Buka      http_handlers_;
336e69e4ee64c466730b98fb7fa3049aabcc85f8984Vitaly Buka  std::map<std::string, provider::HttpServer::RequestHandlerCallback>
337e69e4ee64c466730b98fb7fa3049aabcc85f8984Vitaly Buka      https_handlers_;
33811b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
3391e3636732171afb8cceb9e5cb835ec6a93787dbaVitaly Buka  StrictMock<provider::test::MockConfigStore> config_store_;
340727f3e675fece0ebdcdb0bf0aaf083c374d64d95Vitaly Buka  StrictMock<provider::test::FakeTaskRunner> task_runner_;
3411e3636732171afb8cceb9e5cb835ec6a93787dbaVitaly Buka  StrictMock<provider::test::MockHttpClient> http_client_;
3421e3636732171afb8cceb9e5cb835ec6a93787dbaVitaly Buka  StrictMock<provider::test::MockNetwork> network_;
3431e3636732171afb8cceb9e5cb835ec6a93787dbaVitaly Buka  StrictMock<provider::test::MockDnsServiceDiscovery> dns_sd_;
3441e3636732171afb8cceb9e5cb835ec6a93787dbaVitaly Buka  StrictMock<provider::test::MockHttpServer> http_server_;
3451e3636732171afb8cceb9e5cb835ec6a93787dbaVitaly Buka  StrictMock<provider::test::MockWifi> wifi_;
3461e3636732171afb8cceb9e5cb835ec6a93787dbaVitaly Buka  StrictMock<provider::test::MockBluetooth> bluetooth_;
34711b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
3481e3636732171afb8cceb9e5cb835ec6a93787dbaVitaly Buka  std::vector<provider::Network::ConnectionChangedCallback> network_callbacks_;
349ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka
35011b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  std::unique_ptr<weave::Device> device_;
35111b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka};
35211b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
353ef213d7f63585accbb7ac9bd5112aeeb1b593c9dVitaly BukaTEST_F(WeaveTest, Mocks) {
354a8ece8f8534ca9b551f93bdba2982f40aff3d619Vitaly Buka  // Test checks if mock implements entire interface and mock can be
355a8ece8f8534ca9b551f93bdba2982f40aff3d619Vitaly Buka  // instantiated.
356a8ece8f8534ca9b551f93bdba2982f40aff3d619Vitaly Buka  test::MockDevice device;
357ef213d7f63585accbb7ac9bd5112aeeb1b593c9dVitaly Buka  test::MockCommand command;
358a8ece8f8534ca9b551f93bdba2982f40aff3d619Vitaly Buka}
359a8ece8f8534ca9b551f93bdba2982f40aff3d619Vitaly Buka
36011b2f2382db08ce26f4c4875a4e2d77586165720Vitaly BukaTEST_F(WeaveTest, StartMinimal) {
361c5bdd173a217503710bf1d700a03bfe9a614bb4aVitaly Buka  device_ = weave::Device::Create(&config_store_, &task_runner_, &http_client_,
362c5bdd173a217503710bf1d700a03bfe9a614bb4aVitaly Buka                                  &network_, nullptr, nullptr, &wifi_, nullptr);
363b1041e7c3cc58ca919e2924028c03978c7864c5cVitaly Buka}
364b1041e7c3cc58ca919e2924028c03978c7864c5cVitaly Buka
365b1041e7c3cc58ca919e2924028c03978c7864c5cVitaly BukaTEST_F(WeaveTest, StartNoWifi) {
366b1041e7c3cc58ca919e2924028c03978c7864c5cVitaly Buka  InitNetwork();
367b1041e7c3cc58ca919e2924028c03978c7864c5cVitaly Buka  InitHttpServer();
368beddc6023ef95fdf2c45ad9a300411a2b3895692Vitaly Buka  InitDnsSd();
369beddc6023ef95fdf2c45ad9a300411a2b3895692Vitaly Buka  InitDnsSdPublishing(false, "CB");
370b1041e7c3cc58ca919e2924028c03978c7864c5cVitaly Buka
371c5bdd173a217503710bf1d700a03bfe9a614bb4aVitaly Buka  device_ = weave::Device::Create(&config_store_, &task_runner_, &http_client_,
372c5bdd173a217503710bf1d700a03bfe9a614bb4aVitaly Buka                                  &network_, &dns_sd_, &http_server_, nullptr,
373c5bdd173a217503710bf1d700a03bfe9a614bb4aVitaly Buka                                  &bluetooth_);
374551a82bbefbfd6dc83309eec440a41ca737062b4Alex Vakulenko  device_->AddTraitDefinitionsFromJson(kTraitDefs);
37534668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka  EXPECT_TRUE(
37634668e731bb194b443bc0e6029d6d3583f08de28Vitaly Buka      device_->AddComponent("myComponent", {"trait1", "trait2"}, nullptr));
377b1041e7c3cc58ca919e2924028c03978c7864c5cVitaly Buka
378b1041e7c3cc58ca919e2924028c03978c7864c5cVitaly Buka  task_runner_.Run();
37911b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka}
38011b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
381ca365fb44ec9064043375936c28434b3950a98a3Vitaly Bukaclass WeaveBasicTest : public WeaveTest {
382ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka public:
383ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka  void SetUp() override {
384ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka    WeaveTest::SetUp();
3853884ce15b28039b7c73cf2e79a4c060ca3701bf3Vitaly Buka
386ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka    InitDefaultExpectations();
387beddc6023ef95fdf2c45ad9a300411a2b3895692Vitaly Buka    InitDnsSdPublishing(false, "DB");
388ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka  }
389ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka};
390ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka
391ca365fb44ec9064043375936c28434b3950a98a3Vitaly BukaTEST_F(WeaveBasicTest, Start) {
39211b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  StartDevice();
39311b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka}
39411b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
395ca365fb44ec9064043375936c28434b3950a98a3Vitaly BukaTEST_F(WeaveBasicTest, Register) {
396747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka  EXPECT_CALL(network_, OpenSslSocket(_, _, _)).WillRepeatedly(Return());
39711b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  StartDevice();
39811b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
39911b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  auto draft = CreateDictionaryValue(kDeviceResource);
40011b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  auto response = CreateDictionaryValue(kRegistrationResponse);
40111b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  response->Set("deviceDraft", draft->DeepCopy());
4020d7aac840eaf1cfc14af1e5e39f3fe281d86ead5Vitaly Buka  ExpectRequest(HttpClient::Method::kPatch,
4030d7aac840eaf1cfc14af1e5e39f3fe281d86ead5Vitaly Buka                "https://www.googleapis.com/weave/v1/registrationTickets/"
4040d7aac840eaf1cfc14af1e5e39f3fe281d86ead5Vitaly Buka                "TICKET_ID?key=TEST_API_KEY",
4050d7aac840eaf1cfc14af1e5e39f3fe281d86ead5Vitaly Buka                ValueToString(*response));
40611b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
40711b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  response = CreateDictionaryValue(kRegistrationFinalResponse);
40811b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka  response->Set("deviceDraft", draft->DeepCopy());
4090d7aac840eaf1cfc14af1e5e39f3fe281d86ead5Vitaly Buka  ExpectRequest(HttpClient::Method::kPost,
4100d7aac840eaf1cfc14af1e5e39f3fe281d86ead5Vitaly Buka                "https://www.googleapis.com/weave/v1/registrationTickets/"
4110d7aac840eaf1cfc14af1e5e39f3fe281d86ead5Vitaly Buka                "TICKET_ID/finalize?key=TEST_API_KEY",
4120d7aac840eaf1cfc14af1e5e39f3fe281d86ead5Vitaly Buka                ValueToString(*response));
41311b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
4141a42e1466de3edd0c79215b739cd8e929ef8a7e8Vitaly Buka  ExpectRequest(HttpClient::Method::kPost,
4151a42e1466de3edd0c79215b739cd8e929ef8a7e8Vitaly Buka                "https://accounts.google.com/o/oauth2/token",
41611b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka                kAuthTokenResponse);
41711b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
41872d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka  ExpectRequest(HttpClient::Method::kPost, HasSubstr("upsertLocalAuthInfo"),
41972d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka                {});
42072d8d1611efb8c0dd87d466e971bea9468b7c3a1Vitaly Buka
421beddc6023ef95fdf2c45ad9a300411a2b3895692Vitaly Buka  InitDnsSdPublishing(true, "DB");
42211b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
42312870bd07dd3c8f44528638a9c290b72e22d32d2Vitaly Buka  bool done = false;
424747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka  device_->Register("TICKET_ID", base::Bind([this, &done](ErrorPtr error) {
425747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka                      EXPECT_FALSE(error);
42612870bd07dd3c8f44528638a9c290b72e22d32d2Vitaly Buka                      done = true;
42712870bd07dd3c8f44528638a9c290b72e22d32d2Vitaly Buka                      task_runner_.Break();
42812870bd07dd3c8f44528638a9c290b72e22d32d2Vitaly Buka                      EXPECT_EQ("CLOUD_ID", device_->GetSettings().cloud_id);
429747634273144e0df7b37475375ad4790b6a7b0e8Vitaly Buka                    }));
43012870bd07dd3c8f44528638a9c290b72e22d32d2Vitaly Buka  task_runner_.Run();
43112870bd07dd3c8f44528638a9c290b72e22d32d2Vitaly Buka  EXPECT_TRUE(done);
4320a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka
4330a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka  done = false;
43448a8669ddc2e8d785aad9ad18a5abbf8f1224fdeVitaly Buka  device_->Register("TICKET_ID2", base::Bind([this, &done](ErrorPtr error) {
43548a8669ddc2e8d785aad9ad18a5abbf8f1224fdeVitaly Buka                      EXPECT_TRUE(error->HasError("already_registered"));
43648a8669ddc2e8d785aad9ad18a5abbf8f1224fdeVitaly Buka                      done = true;
43748a8669ddc2e8d785aad9ad18a5abbf8f1224fdeVitaly Buka                      task_runner_.Break();
43848a8669ddc2e8d785aad9ad18a5abbf8f1224fdeVitaly Buka                      EXPECT_EQ("CLOUD_ID", device_->GetSettings().cloud_id);
43948a8669ddc2e8d785aad9ad18a5abbf8f1224fdeVitaly Buka                    }));
4400a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka  task_runner_.Run();
4410a8ab9973e1fdf6b41d8f7b49529c9bd97a9071cVitaly Buka  EXPECT_TRUE(done);
44211b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka}
44311b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka
444ca365fb44ec9064043375936c28434b3950a98a3Vitaly Bukaclass WeaveWiFiSetupTest : public WeaveTest {
445ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka public:
446ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka  void SetUp() override {
447ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka    WeaveTest::SetUp();
448ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka
449ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka    InitHttpServer();
450ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka    InitNetwork();
451beddc6023ef95fdf2c45ad9a300411a2b3895692Vitaly Buka    InitDnsSd();
452ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka
453ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka    EXPECT_CALL(network_, GetConnectionState())
454efad5b25439063124eccf100fd79c9489c9705beVitaly Buka        .WillRepeatedly(Return(provider::Network::State::kOnline));
455ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka  }
456ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka};
457ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka
458ca365fb44ec9064043375936c28434b3950a98a3Vitaly BukaTEST_F(WeaveWiFiSetupTest, StartOnlineNoPrevSsid) {
459ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka  StartDevice();
460ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka
461ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka  // Short disconnect.
46235f317dacc5176ccc8a7b2b80eeb518ed1f632cdVitaly Buka  NotifyNetworkChanged(provider::Network::State::kOffline, {});
463efad5b25439063124eccf100fd79c9489c9705beVitaly Buka  NotifyNetworkChanged(provider::Network::State::kOnline,
4643884ce15b28039b7c73cf2e79a4c060ca3701bf3Vitaly Buka                       base::TimeDelta::FromSeconds(10));
465ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka  task_runner_.Run();
466ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka
467ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka  // Long disconnect.
46835f317dacc5176ccc8a7b2b80eeb518ed1f632cdVitaly Buka  NotifyNetworkChanged(Network::State::kOffline, {});
469ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka  auto offline_from = task_runner_.GetClock()->Now();
470a05eadb5a34b90e3aec184c41b9e3481e18902b3Vitaly Buka  EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
471ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka      .WillOnce(InvokeWithoutArgs([this, offline_from]() {
472ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka        EXPECT_GT(task_runner_.GetClock()->Now() - offline_from,
473ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka                  base::TimeDelta::FromMinutes(1));
474caf42bdc1c8cb18c2663f2c8ade3f47c436f8637Vitaly Buka        task_runner_.Break();
475ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka      }));
476ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka  task_runner_.Run();
477ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka}
478ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka
479ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka// If device has previously configured WiFi it will run AP for limited time
480ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka// after which it will try to re-connect.
481ca365fb44ec9064043375936c28434b3950a98a3Vitaly BukaTEST_F(WeaveWiFiSetupTest, StartOnlineWithPrevSsid) {
482ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka  EXPECT_CALL(config_store_, LoadSettings())
483ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka      .WillRepeatedly(Return(R"({"last_configured_ssid": "TEST_ssid"})"));
484ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka  StartDevice();
485ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka
486ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka  // Long disconnect.
48735f317dacc5176ccc8a7b2b80eeb518ed1f632cdVitaly Buka  NotifyNetworkChanged(Network::State::kOffline, {});
488ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka
489ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka  for (int i = 0; i < 5; ++i) {
490ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka    auto offline_from = task_runner_.GetClock()->Now();
491ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka    // Temporarily offline mode.
492a05eadb5a34b90e3aec184c41b9e3481e18902b3Vitaly Buka    EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
493ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka        .WillOnce(InvokeWithoutArgs([this, &offline_from]() {
494ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka          EXPECT_GT(task_runner_.GetClock()->Now() - offline_from,
495ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka                    base::TimeDelta::FromMinutes(1));
496ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka          task_runner_.Break();
497ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka        }));
498ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka    task_runner_.Run();
499ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka
500ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka    // Try to reconnect again.
501ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka    offline_from = task_runner_.GetClock()->Now();
5021fd619a3ff996aac12bd0ef2ed99090e4dc6b6ddVitaly Buka    EXPECT_CALL(wifi_, StopAccessPoint())
503ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka        .WillOnce(InvokeWithoutArgs([this, offline_from]() {
504ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka          EXPECT_GT(task_runner_.GetClock()->Now() - offline_from,
505ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka                    base::TimeDelta::FromMinutes(5));
506ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka          task_runner_.Break();
507ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka        }));
508ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka    task_runner_.Run();
509ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka  }
510ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka
511efad5b25439063124eccf100fd79c9489c9705beVitaly Buka  NotifyNetworkChanged(Network::State::kOnline, {});
512ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka  task_runner_.Run();
513ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka}
514ca365fb44ec9064043375936c28434b3950a98a3Vitaly Buka
515caf42bdc1c8cb18c2663f2c8ade3f47c436f8637Vitaly BukaTEST_F(WeaveWiFiSetupTest, StartOfflineWithSsid) {
516caf42bdc1c8cb18c2663f2c8ade3f47c436f8637Vitaly Buka  EXPECT_CALL(config_store_, LoadSettings())
517caf42bdc1c8cb18c2663f2c8ade3f47c436f8637Vitaly Buka      .WillRepeatedly(Return(R"({"last_configured_ssid": "TEST_ssid"})"));
518caf42bdc1c8cb18c2663f2c8ade3f47c436f8637Vitaly Buka  EXPECT_CALL(network_, GetConnectionState())
51935f317dacc5176ccc8a7b2b80eeb518ed1f632cdVitaly Buka      .WillRepeatedly(Return(Network::State::kOffline));
520caf42bdc1c8cb18c2663f2c8ade3f47c436f8637Vitaly Buka
521caf42bdc1c8cb18c2663f2c8ade3f47c436f8637Vitaly Buka  auto offline_from = task_runner_.GetClock()->Now();
522a05eadb5a34b90e3aec184c41b9e3481e18902b3Vitaly Buka  EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
523caf42bdc1c8cb18c2663f2c8ade3f47c436f8637Vitaly Buka      .WillOnce(InvokeWithoutArgs([this, &offline_from]() {
524caf42bdc1c8cb18c2663f2c8ade3f47c436f8637Vitaly Buka        EXPECT_GT(task_runner_.GetClock()->Now() - offline_from,
525caf42bdc1c8cb18c2663f2c8ade3f47c436f8637Vitaly Buka                  base::TimeDelta::FromMinutes(1));
526caf42bdc1c8cb18c2663f2c8ade3f47c436f8637Vitaly Buka        task_runner_.Break();
527caf42bdc1c8cb18c2663f2c8ade3f47c436f8637Vitaly Buka      }));
528caf42bdc1c8cb18c2663f2c8ade3f47c436f8637Vitaly Buka
529caf42bdc1c8cb18c2663f2c8ade3f47c436f8637Vitaly Buka  StartDevice();
530caf42bdc1c8cb18c2663f2c8ade3f47c436f8637Vitaly Buka}
531caf42bdc1c8cb18c2663f2c8ade3f47c436f8637Vitaly Buka
53265e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly BukaTEST_F(WeaveWiFiSetupTest, OfflineLongTimeWithNoSsid) {
53365e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka  EXPECT_CALL(network_, GetConnectionState())
53465e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka      .WillRepeatedly(Return(Network::State::kOffline));
53565e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka  NotifyNetworkChanged(provider::Network::State::kOnline,
53665e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka                       base::TimeDelta::FromHours(15));
53765e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka
53865e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka  {
53965e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka    InSequence s;
54065e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka    auto time_stamp = task_runner_.GetClock()->Now();
54165e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka
54265e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka    EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
54365e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka        .WillOnce(InvokeWithoutArgs([this, &time_stamp]() {
54465e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka          EXPECT_LE(task_runner_.GetClock()->Now() - time_stamp,
54565e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka                    base::TimeDelta::FromMinutes(1));
54665e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka          time_stamp = task_runner_.GetClock()->Now();
54765e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka        }));
54865e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka
54965e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka    EXPECT_CALL(wifi_, StopAccessPoint())
55065e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka        .WillOnce(InvokeWithoutArgs([this, &time_stamp]() {
55165e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka          EXPECT_GT(task_runner_.GetClock()->Now() - time_stamp,
55265e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka                    base::TimeDelta::FromMinutes(5));
55365e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka          time_stamp = task_runner_.GetClock()->Now();
55465e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka          task_runner_.Break();
55565e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka        }));
55665e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka  }
55765e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka
55865e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka  StartDevice();
55965e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka}
56065e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka
56165e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly BukaTEST_F(WeaveWiFiSetupTest, OfflineLongTimeWithSsid) {
56265e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka  EXPECT_CALL(config_store_, LoadSettings())
56365e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka      .WillRepeatedly(Return(R"({"last_configured_ssid": "TEST_ssid"})"));
56465e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka  EXPECT_CALL(network_, GetConnectionState())
56565e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka      .WillRepeatedly(Return(Network::State::kOffline));
56665e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka  NotifyNetworkChanged(provider::Network::State::kOnline,
56765e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka                       base::TimeDelta::FromHours(15));
56865e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka
56965e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka  {
57065e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka    InSequence s;
57165e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka    auto time_stamp = task_runner_.GetClock()->Now();
57265e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka    for (size_t i = 0; i < 10; ++i) {
57365e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka      EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
57465e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka          .WillOnce(InvokeWithoutArgs([this, &time_stamp]() {
57565e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka            EXPECT_GT(task_runner_.GetClock()->Now() - time_stamp,
57665e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka                      base::TimeDelta::FromMinutes(1));
57765e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka            time_stamp = task_runner_.GetClock()->Now();
57865e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka          }));
57965e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka
58065e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka      EXPECT_CALL(wifi_, StopAccessPoint())
58165e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka          .WillOnce(InvokeWithoutArgs([this, &time_stamp]() {
58265e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka            EXPECT_GT(task_runner_.GetClock()->Now() - time_stamp,
58365e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka                      base::TimeDelta::FromMinutes(5));
58465e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka            time_stamp = task_runner_.GetClock()->Now();
58565e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka          }));
58665e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka    }
58765e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka
58865e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka    EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
58965e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka        .WillOnce(InvokeWithoutArgs([this]() { task_runner_.Break(); }));
59065e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka  }
59165e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka
59265e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka  StartDevice();
59365e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka}
59465e1f21f13102b076156e2e6a07486c06f5b25d1Vitaly Buka
59511b2f2382db08ce26f4c4875a4e2d77586165720Vitaly Buka}  // namespace weave
596