1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/network/network_state.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/basictypes.h"
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/values.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "third_party/cros_system_api/dbus/service_constants.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace chromeos {
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
18a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// StringValue that skips the DCHECK in the constructor for valid UTF8.
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class TestStringValue : public base::Value {
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
21b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  explicit TestStringValue(const std::string& in_value)
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : base::Value(TYPE_STRING),
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        value_(in_value) {
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
26b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  virtual ~TestStringValue() {
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Overridden from Value:
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual bool GetAsString(std::string* out_value) const OVERRIDE {
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (out_value)
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      *out_value = value_;
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual TestStringValue* DeepCopy() const OVERRIDE {
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return new TestStringValue(value_);
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual bool Equals(const base::Value* other) const OVERRIDE {
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (other->GetType() != GetType())
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return false;
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string lhs, rhs;
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return GetAsString(&lhs) && other->GetAsString(&rhs) && lhs == rhs;
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string value_;
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class NetworkStateTest : public testing::Test {
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  NetworkStateTest() : network_state_("test_path") {
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected:
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool SetStringProperty(const std::string& key, const std::string& value) {
58a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    TestStringValue* string_value = new TestStringValue(value);
59a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    bool res = network_state_.PropertyChanged(key, *string_value);
60a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    properties_.SetWithoutPathExpansion(key, string_value);
61a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return res;
62a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
63a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
64a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  bool SignalInitialPropertiesReceived() {
65a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return network_state_.InitialPropertiesReceived(properties_);
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  NetworkState network_state_;
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
71a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  base::DictionaryValue properties_;
72a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(NetworkStateTest);
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Setting kNameProperty should set network name after call to
794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// InitialPropertiesReceived().
804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST_F(NetworkStateTest, NameAscii) {
814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_TRUE(SetStringProperty(shill::kTypeProperty, shill::kTypeVPN));
824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  std::string network_setname = "Name TEST";
844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_TRUE(SetStringProperty(shill::kNameProperty, network_setname));
854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_FALSE(SignalInitialPropertiesReceived());
864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(network_state_.name(), network_setname);
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST_F(NetworkStateTest, NameAsciiWithNull) {
904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_TRUE(SetStringProperty(shill::kTypeProperty, shill::kTypeVPN));
914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  std::string network_setname = "Name TEST\x00xxx";
934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  std::string network_setname_result = "Name TEST";
944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_TRUE(SetStringProperty(shill::kNameProperty, network_setname));
954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_FALSE(SignalInitialPropertiesReceived());
964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(network_state_.name(), network_setname_result);
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Truncates invalid UTF-8
1004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST_F(NetworkStateTest, NameTruncateInvalid) {
1014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_TRUE(SetStringProperty(shill::kTypeProperty, shill::kTypeVPN));
1024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  std::string network_setname = "SSID TEST \x01\xff!";
1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  std::string network_setname_result = "SSID TEST \xEF\xBF\xBD\xEF\xBF\xBD!";
1054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_TRUE(SetStringProperty(shill::kNameProperty, network_setname));
1064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_TRUE(SignalInitialPropertiesReceived());
1074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(network_state_.name(), network_setname_result);
1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// If HexSSID doesn't exist, fallback to NameProperty.
1114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST_F(NetworkStateTest, SsidFromName) {
1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_TRUE(SetStringProperty(shill::kTypeProperty, shill::kTypeWifi));
1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string wifi_utf8 = "UTF-8 \u3042\u3044\u3046";
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string wifi_utf8_result = "UTF-8 \xE3\x81\x82\xE3\x81\x84\xE3\x81\x86";
11668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_TRUE(SetStringProperty(shill::kNameProperty, wifi_utf8));
1174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_FALSE(SignalInitialPropertiesReceived());
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(network_state_.name(), wifi_utf8_result);
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// latin1 SSID -> UTF8 SSID (Hex)
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(NetworkStateTest, SsidLatin) {
1234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_TRUE(SetStringProperty(shill::kTypeProperty, shill::kTypeWifi));
1244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string wifi_latin1 = "latin-1 \xc0\xcb\xcc\xd6\xfb";
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string wifi_latin1_hex =
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::HexEncode(wifi_latin1.c_str(), wifi_latin1.length());
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string wifi_latin1_result = "latin-1 \u00c0\u00cb\u00cc\u00d6\u00fb";
12968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_FALSE(SetStringProperty(shill::kWifiHexSsid, wifi_latin1_hex));
130a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_TRUE(SignalInitialPropertiesReceived());
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(network_state_.name(), wifi_latin1_result);
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Hex SSID
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(NetworkStateTest, SsidHex) {
1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_TRUE(SetStringProperty(shill::kTypeProperty, shill::kTypeWifi));
1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string wifi_hex_result = "This is HEX SSID!";
1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  std::string wifi_hex =
1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      base::HexEncode(wifi_hex_result.c_str(), wifi_hex_result.length());
14168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_FALSE(SetStringProperty(shill::kWifiHexSsid, wifi_hex));
142a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_TRUE(SignalInitialPropertiesReceived());
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(network_state_.name(), wifi_hex_result);
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace chromeos
147