blob: 973295ae2a256e382b2c834691ed28d84661e248 [file] [log] [blame]
// Copyright 2015 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <map>
#include <memory>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/callback.h"
#include "base/callback_list.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "thermald/key_value_publisher.h"
#include "thermald/mock_key_value_subscriber.h"
#include "thermald/mock_temperature_monitor.h"
#include "thermald/thermal_zone.h"
#include "thermald/thermal_zone_controller.h"
using std::make_pair;
using std::string;
using std::unique_ptr;
using std::vector;
using testing::_;
using testing::AnyNumber;
using testing::Invoke;
using testing::InSequence;
namespace thermald {
static const char *kTemp0Name = "temperature 0";
static const char *kTemp1Name = "temperature 1";
static const int kState2Sensor0ActivationThreshold = 60000;
static const int kState2S0BottomThreshold = 55000;
static const int kState2S1ActivationThreshold = 70000;
static const int kState2S1BottomThreshold = 65000;
static const char *kOutput0Key = "output0";
static const char *kOutput1Key = "output1";
static const int kState1Output0Value = 13;
static const int kState1Output1Value = 42;
static const int kState2Output0Value = 67;
static const int kState2Output1Value = 79;
static const char *kZoneStateKey = "thermal_zone.zone 0.state";
class ThermalZoneControllerTest : public testing::Test {
protected:
ThermalZoneControllerTest();
virtual ~ThermalZoneControllerTest();
static void SetUpTestCase();
static void AddThermalState(
int state_id,
int activation_threshold_0, int bottom_threshold_0,
int activation_threshold_1, int bottom_threshold_1,
const vector<ThermalStateOutput> &outputs);
bool StartZoneController();
unique_ptr<ThermalZoneController> zone_controller_;
KeyValuePublisher output_publisher_;
#if BASE_VER < 860220
std::unique_ptr<KeyValuePublisher::Subscription> subscription_;
#else
base::CallbackListSubscription subscription_;
#endif
MockTemperatureMonitor temp_monitor_0_;
MockTemperatureMonitor temp_monitor_1_;
static ThermalZone thermal_zone_;
};
ThermalZone ThermalZoneControllerTest::thermal_zone_;
ThermalZoneControllerTest::ThermalZoneControllerTest()
: temp_monitor_0_(kTemp0Name), temp_monitor_1_(kTemp1Name) {
vector<TemperatureMonitorInterface *> temp_monitors;
temp_monitors.push_back(&temp_monitor_0_);
temp_monitors.push_back(&temp_monitor_1_);
zone_controller_.reset(new ThermalZoneController(&thermal_zone_,
&output_publisher_,
temp_monitors));
}
ThermalZoneControllerTest::~ThermalZoneControllerTest() {
if (zone_controller_.get()) {
EXPECT_CALL(temp_monitor_0_, OnSubscriberRemoved()).Times(AnyNumber());
EXPECT_CALL(temp_monitor_1_, OnSubscriberRemoved()).Times(AnyNumber());
zone_controller_->Stop();
zone_controller_.reset();
}
}
static inline void AddOutput(vector<ThermalStateOutput> *outputs,
const string &key, int value) {
ThermalStateOutput o;
o.key = key;
o.value = value;
outputs->push_back(o);
}
void ThermalZoneControllerTest::SetUpTestCase() {
thermal_zone_.name = "zone 0";
vector<ThermalStateOutput> outputs;
AddOutput(&outputs, kOutput0Key, kState2Output0Value);
AddOutput(&outputs, kOutput1Key, kState2Output1Value);
AddThermalState(2, kState2Sensor0ActivationThreshold,
kState2S0BottomThreshold,
kState2S1ActivationThreshold,
kState2S1BottomThreshold, outputs);
outputs.clear();
AddOutput(&outputs, kOutput0Key, kState1Output0Value);
AddOutput(&outputs, kOutput1Key, kState1Output1Value);
AddThermalState(1, kTemp0K, kTemp0K, kTemp0K, kTemp0K, outputs);
}
void ThermalZoneControllerTest::AddThermalState(
int state_id,
int activation_threshold_0, int bottom_threshold_0,
int activation_threshold_1, int bottom_threshold_1,
const vector<ThermalStateOutput> &outputs) {
std::unique_ptr<ThermalState> state = std::make_unique<ThermalState>();
ThermalPointThresholds thresholds;
state->id = state_id;
thresholds.activation = activation_threshold_0;
thresholds.bottom = bottom_threshold_0;
state->thresholds.insert(make_pair(kTemp0Name, thresholds));
thresholds.activation = activation_threshold_1;
thresholds.bottom = bottom_threshold_1;
state->thresholds.insert(make_pair(kTemp1Name, thresholds));
state->outputs = outputs;
thermal_zone_.states.push_back(std::move(state));
}
bool ThermalZoneControllerTest::StartZoneController() {
EXPECT_CALL(temp_monitor_0_, Subscribe());
EXPECT_CALL(temp_monitor_1_, Subscribe());
zone_controller_->Start();
return true;
}
TEST_F(ThermalZoneControllerTest, SubscribesToTemperatureMonitorsWhenStarted) {
EXPECT_CALL(temp_monitor_0_, Subscribe());
EXPECT_CALL(temp_monitor_1_, Subscribe());
zone_controller_->Start();
};
TEST_F(ThermalZoneControllerTest,
UnsubscribesFromTemperatureMonitorsWhenStopped) {
ASSERT_TRUE(StartZoneController());
EXPECT_CALL(temp_monitor_0_, OnSubscriberRemoved());
EXPECT_CALL(temp_monitor_1_, OnSubscriberRemoved());
zone_controller_->Stop();
}
TEST_F(ThermalZoneControllerTest,
UnsubscribesFromTemperatureMonitorsWhenDeleted) {
ASSERT_TRUE(StartZoneController());
EXPECT_CALL(temp_monitor_0_, OnSubscriberRemoved());
EXPECT_CALL(temp_monitor_1_, OnSubscriberRemoved());
zone_controller_.reset();
}
TEST_F(ThermalZoneControllerTest, SetsOutputsWhenNewStateIsEntered) {
MockKeyValueSubscriber sub;
auto s = output_publisher_.Subscribe(
base::Bind(&MockKeyValueSubscriber::Set, base::Unretained(&sub)));
ASSERT_TRUE(StartZoneController());
EXPECT_CALL(sub, Set(kOutput0Key, kState1Output0Value));
EXPECT_CALL(sub, Set(kOutput1Key, kState1Output1Value));
EXPECT_CALL(sub, Set(kZoneStateKey, 1));
// Enter thermal state 1.
temp_monitor_0_.NotifySubscribers(kState2Sensor0ActivationThreshold - 1);
EXPECT_CALL(sub, Set(kOutput0Key, kState2Output0Value));
EXPECT_CALL(sub, Set(kOutput1Key, kState2Output1Value));
EXPECT_CALL(sub, Set(kZoneStateKey, 2));
// Enter thermal state 2.
temp_monitor_1_.NotifySubscribers(kState2S1ActivationThreshold);
}
} // namespace thermald