cashew: data plans: used bytes should be optional for unlimited plans BUG=chromium-os:8231,chromium-os:7775 TEST=unit tests Change-Id: I2042c7fe4c8cd93172a8719fd8da020bc164cb7b Review URL: http://codereview.chromium.org/4114002
diff --git a/src/data_plan.cc b/src/data_plan.cc index 1a6b7f5..6b74e46 100644 --- a/src/data_plan.cc +++ b/src/data_plan.cc
@@ -97,10 +97,13 @@ plan[kCellularDataPlanEndTime].writer().append_int64( end_time_.ToInternalValue()); // omit max bytes field for unlimited plans - // can libcros/Chrome deal? if not, can set this to int64 max. if (type_ != kTypeUnlimited) { plan[kCellularDataPlanDataBytesMax].writer().append_int64(data_bytes_max_); } + // always send used bytes field, even if we had to assume a value of 0 + // because this is an unlimited plan and the property was absent in the + // usage API replies that we received + // TODO(vlaviano): we'll be able to do better when we have local counters plan[kCellularDataPlanDataBytesUsed].writer().append_int64(data_bytes_used_); return plan; } @@ -162,8 +165,14 @@ int used_bytes = 0; if (!value->GetInteger(kCrosUsageDataPlanUsedBytesProperty, &used_bytes)) { - LOG(WARNING) << "FromDictionaryValue: no used bytes property"; - return NULL; + // used bytes is required for metered plans, optional for unlimited plans + if (plan_type != kTypeUnlimited) { + LOG(WARNING) << "FromDictionaryValue: no used bytes property"; + return NULL; + } else { + DLOG(INFO) + << "FromDictionaryValue: no used bytes property (using default of 0)"; + } } if (used_bytes < 0) { LOG(WARNING) << "FromDictionaryValue: used bytes is negative";
diff --git a/src/data_plan_unittest.cc b/src/data_plan_unittest.cc index b5f04db..fe4e15d 100644 --- a/src/data_plan_unittest.cc +++ b/src/data_plan_unittest.cc
@@ -2,23 +2,87 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <base/json/json_reader.h> +#include <base/scoped_ptr.h> #include <gtest/gtest.h> #include "src/data_plan.h" +#include "src/policy.h" namespace cashew { // test fixture for DataPlan unit tests class DataPlanTest: public ::testing::Test { protected: - DataPlanTest() {} - virtual ~DataPlanTest() {} - virtual void SetUp() {} - virtual void TearDown() {} + DataPlanTest() : policy_(NULL) {} + + virtual ~DataPlanTest() { + EXPECT_TRUE(policy_ == NULL); + } + + virtual void SetUp() { + EXPECT_TRUE(policy_ == NULL); + policy_ = Policy::GetPolicy(kTestCarrierName); + ASSERT_TRUE(policy_ != NULL); + } + + virtual void TearDown() { + delete policy_; + policy_ = NULL; + } + + // hardcoded JSON data plan representations + static const char *kMeteredWithUsedBytesJSON; + static const char *kMeteredWithNoUsedBytesJSON; + static const char *kUnlimitedWithUsedBytesJSON; + static const char *kUnlimitedWithNoUsedBytesJSON; + + // test carrier for constructing policy + static const char *kTestCarrierName; + + Policy *policy_; }; typedef DataPlanTest DataPlanDeathTest; +const char *DataPlanTest::kMeteredWithUsedBytesJSON = + "{\"lastUpdate\" : \"2010-09-20T12:01:00Z\"," + "\"planName\" : \"Super-Awesome Chromium OS Plan\"," + "\"planType\" : \"METERED_PAID\"," + "\"maxBytes\" : 104857600," + "\"usedBytes\" : 52428800," + "\"expirationTime\" : \"2010-09-30T23:59:59\"," + "\"startTime\" : \"2010-09-01T00:00:00\"" + "}"; + +const char *DataPlanTest::kMeteredWithNoUsedBytesJSON = + "{\"lastUpdate\" : \"2010-09-20T12:01:00Z\"," + "\"planName\" : \"Super-Awesome Chromium OS Plan\"," + "\"planType\" : \"METERED_PAID\"," + "\"maxBytes\" : 104857600," + "\"expirationTime\" : \"2010-09-30T23:59:59\"," + "\"startTime\" : \"2010-09-01T00:00:00\"" + "}"; + +const char *DataPlanTest::kUnlimitedWithUsedBytesJSON = + "{\"lastUpdate\" : \"2010-09-20T12:01:00Z\"," + "\"planName\" : \"All-You-Can-Eat Day Pass\"," + "\"planType\" : \"UNLIMITED\"," + "\"usedBytes\" : 52428800," + "\"expirationTime\" : \"2010-09-20T23:59:59\"," + "\"startTime\" : \"2010-09-20T00:00:00\"" + "}"; + +const char *DataPlanTest::kUnlimitedWithNoUsedBytesJSON = + "{\"lastUpdate\" : \"2010-09-20T12:01:00Z\"," + "\"planName\" : \"All-You-Can-Eat Day Pass\"," + "\"planType\" : \"UNLIMITED\"," + "\"expirationTime\" : \"2010-09-20T23:59:59\"," + "\"startTime\" : \"2010-09-20T00:00:00\"" + "}"; + +const char *DataPlanTest::kTestCarrierName = "Test Carrier"; + TEST_F(DataPlanTest, UtcTimeString) { static const char *kTimeStringToTest = "2010-09-20T23:59:59Z"; base::Time time; @@ -81,4 +145,60 @@ "Check failed: 'time_out' Must be non NULL"); } +TEST_F(DataPlanTest, FromDictionaryValueMeteredWithUsedBytes) { + scoped_ptr<Value> value(base::JSONReader::Read(kMeteredWithUsedBytesJSON, + true)); + ASSERT_TRUE(value != NULL); + ASSERT_TRUE(value->IsType(Value::TYPE_DICTIONARY)); + const DictionaryValue *dict_value = + static_cast<const DictionaryValue*>(value.get()); + DataPlan *plan = DataPlan::FromDictionaryValue(dict_value, policy_); + // we expect the call to have succeeeded, with the new data plan's used bytes + // property set to the value that was present in the JSON representation + ASSERT_TRUE(plan != NULL); + EXPECT_EQ(52428800, plan->GetDataBytesUsed()); +} + +TEST_F(DataPlanTest, FromDictonaryValueMeteredWithNoUsedBytes) { + scoped_ptr<Value> value(base::JSONReader::Read(kMeteredWithNoUsedBytesJSON, + true)); + ASSERT_TRUE(value != NULL); + ASSERT_TRUE(value->IsType(Value::TYPE_DICTIONARY)); + const DictionaryValue *dict_value = + static_cast<const DictionaryValue*>(value.get()); + DataPlan *plan = DataPlan::FromDictionaryValue(dict_value, policy_); + // the JSON representation for metered plans must include used bytes, so we + // expect the call to have failed + EXPECT_TRUE(plan == NULL); +} + +TEST_F(DataPlanTest, FromDictionaryValueUnlimitedWithUsedBytes) { + scoped_ptr<Value> value(base::JSONReader::Read(kUnlimitedWithUsedBytesJSON, + true)); + ASSERT_TRUE(value != NULL); + ASSERT_TRUE(value->IsType(Value::TYPE_DICTIONARY)); + const DictionaryValue *dict_value = + static_cast<const DictionaryValue*>(value.get()); + DataPlan *plan = DataPlan::FromDictionaryValue(dict_value, policy_); + // we expect the call to have succeeeded, with the new data plan's used bytes + // property set to the value that was present in the JSON representation + ASSERT_TRUE(plan != NULL); + EXPECT_EQ(52428800, plan->GetDataBytesUsed()); +} + +TEST_F(DataPlanTest, FromDictionaryValueUnlimitedWithNoUsedBytes) { + scoped_ptr<Value> value(base::JSONReader::Read(kUnlimitedWithNoUsedBytesJSON, + true)); + ASSERT_TRUE(value != NULL); + ASSERT_TRUE(value->IsType(Value::TYPE_DICTIONARY)); + const DictionaryValue *dict_value = + static_cast<const DictionaryValue*>(value.get()); + DataPlan *plan = DataPlan::FromDictionaryValue(dict_value, policy_); + // it's optional for the JSON representation for unlimited plans to include + // used bytes, so we expect the call to have succeeded. The new data plan's + // used bytes property should have been set to the default of 0. + ASSERT_TRUE(plan != NULL); + EXPECT_EQ(0, plan->GetDataBytesUsed()); +} + } // namespace cashew