charge_manager: Add unit tests

Add unit tests for the charge_manager module.

BUG=chrome-os-partner:32003
TEST=`make buildall -j`
BRANCH=Samus

Change-Id: I31962588ca7360e2ffde6b83459505872e2128b9
Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/227620
Reviewed-by: Alec Berg <alecaberg@chromium.org>
This commit is contained in:
Shawn Nematbakhsh
2014-11-05 10:02:01 -08:00
committed by chrome-internal-fetch
parent 06fb4fe0f2
commit cf48a3640c
6 changed files with 315 additions and 1 deletions

View File

@@ -39,4 +39,27 @@ enum adc_channel {
ADC_CH_COUNT
};
/* Charge suppliers */
enum charge_supplier {
CHARGE_SUPPLIER_TEST1,
CHARGE_SUPPLIER_TEST2,
CHARGE_SUPPLIER_TEST3,
CHARGE_SUPPLIER_TEST4,
CHARGE_SUPPLIER_TEST5,
CHARGE_SUPPLIER_TEST6,
CHARGE_SUPPLIER_TEST7,
CHARGE_SUPPLIER_TEST8,
CHARGE_SUPPLIER_TEST9,
CHARGE_SUPPLIER_COUNT
};
/* supplier_priority table defined in board.c */
extern const int supplier_priority[];
/* Set the active charge port. */
void board_set_active_charge_port(int charge_port);
/* Set the charge current limit. */
void board_set_charge_limit(int charge_ma);
#endif /* __BOARD_H */

View File

@@ -194,6 +194,7 @@ int charge_manager_get_active_charge_port(void)
return charge_port;
}
#ifndef TEST_CHARGE_MANAGER
static int hc_pd_power_info(struct host_cmd_handler_args *args)
{
const struct ec_params_usb_pd_power_info *p = args->params;
@@ -289,3 +290,4 @@ static int hc_pd_power_info(struct host_cmd_handler_args *args)
DECLARE_HOST_COMMAND(EC_CMD_USB_PD_POWER_INFO,
hc_pd_power_info,
EC_VER_MASK(0));
#endif /* TEST_CHARGE_MANAGER */

View File

@@ -31,13 +31,14 @@ test-list-host+=thermal flash queue kb_8042 extpwr_gpio console_edit system
test-list-host+=sbs_charging adapter host_command thermal_falco led_spring
test-list-host+=bklight_lid bklight_passthru interrupt timer_dos button
test-list-host+=motion_lid math_util sbs_charging_v2 battery_get_params_smart
test-list-host+=lightbar inductive_charging usb_pd fan
test-list-host+=lightbar inductive_charging usb_pd fan charge_manager
adapter-y=adapter.o
battery_get_params_smart-y=battery_get_params_smart.o
bklight_lid-y=bklight_lid.o
bklight_passthru-y=bklight_passthru.o
button-y=button.o
charge_manager-y=charge_manager.o
console_edit-y=console_edit.o
extpwr_gpio-y=extpwr_gpio.o
flash-y=flash.o

266
test/charge_manager.c Normal file
View File

@@ -0,0 +1,266 @@
/* Copyright 2014 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.
*
* Test charge manager module.
*/
#include "charge_manager.h"
#include "test_util.h"
#include "timer.h"
#include "usb_pd_config.h"
#include "util.h"
#define CHARGE_MANAGER_SLEEP_MS 50
/* Charge supplier priority: lower number indicates higher priority. */
const int supplier_priority[] = {
[CHARGE_SUPPLIER_TEST1] = 0,
[CHARGE_SUPPLIER_TEST2] = 1,
[CHARGE_SUPPLIER_TEST3] = 1,
[CHARGE_SUPPLIER_TEST4] = 1,
[CHARGE_SUPPLIER_TEST5] = 3,
[CHARGE_SUPPLIER_TEST6] = 3,
[CHARGE_SUPPLIER_TEST7] = 5,
[CHARGE_SUPPLIER_TEST8] = 6,
[CHARGE_SUPPLIER_TEST9] = 6,
};
BUILD_ASSERT(ARRAY_SIZE(supplier_priority) == CHARGE_SUPPLIER_COUNT);
static unsigned int active_charge_limit = CHARGE_SUPPLIER_NONE;
static unsigned int active_charge_port = CHARGE_PORT_NONE;
static int new_power_request[PD_PORT_COUNT];
/* Callback functions called by CM on state change */
void board_set_charge_limit(int charge_ma)
{
active_charge_limit = charge_ma;
}
void board_set_active_charge_port(int charge_port)
{
active_charge_port = charge_port;
}
void pd_set_new_power_request(int port)
{
new_power_request[port] = 1;
}
void clear_new_power_requests(void)
{
int i;
for (i = 0; i < PD_PORT_COUNT; ++i)
new_power_request[i] = 0;
}
static void wait_for_charge_manager_refresh(void)
{
msleep(CHARGE_MANAGER_SLEEP_MS);
}
static void initialize_charge_table(int current, int voltage, int ceil)
{
int i, j;
struct charge_port_info charge;
charge.current = current;
charge.voltage = voltage;
for (i = 0; i < PD_PORT_COUNT; ++i) {
charge_manager_set_ceil(i, ceil);
for (j = 0; j < CHARGE_SUPPLIER_COUNT; ++j)
charge_manager_update(j, i, &charge);
}
wait_for_charge_manager_refresh();
}
static int test_initialization(void)
{
int i, j;
struct charge_port_info charge;
/*
* No charge port should be selected until all ports + suppliers
* have reported in with an initial charge.
*/
TEST_ASSERT(active_charge_port == CHARGE_PORT_NONE);
charge.current = 1000;
charge.voltage = 5000;
/* Initialize all supplier/port pairs, except for the last one */
for (i = 0; i < CHARGE_SUPPLIER_COUNT; ++i)
for (j = 0; j < PD_PORT_COUNT; ++j) {
if (i == CHARGE_SUPPLIER_COUNT - 1 &&
j == PD_PORT_COUNT - 1)
break;
charge_manager_update(i, j, &charge);
}
/* Verify no active charge port, since all pairs haven't updated */
wait_for_charge_manager_refresh();
TEST_ASSERT(active_charge_port == CHARGE_PORT_NONE);
/* Update last pair and verify a charge port has been selected */
charge_manager_update(CHARGE_SUPPLIER_COUNT-1,
PD_PORT_COUNT-1,
&charge);
wait_for_charge_manager_refresh();
TEST_ASSERT(active_charge_port != CHARGE_PORT_NONE);
return EC_SUCCESS;
}
static int test_priority(void)
{
struct charge_port_info charge;
/* Initialize table to no charge */
initialize_charge_table(0, 5000, 5000);
TEST_ASSERT(active_charge_port == CHARGE_PORT_NONE);
/*
* Set a 1A charge via a high-priority supplier and a 2A charge via
* a low-priority supplier, and verify the HP supplier is chosen.
*/
charge.current = 2000;
charge.voltage = 5000;
charge_manager_update(CHARGE_SUPPLIER_TEST6, 0, &charge);
charge.current = 1000;
charge_manager_update(CHARGE_SUPPLIER_TEST2, 1, &charge);
wait_for_charge_manager_refresh();
TEST_ASSERT(active_charge_port == 1);
TEST_ASSERT(active_charge_limit == 1000);
/*
* Set a higher charge on a LP supplier and verify we still use the
* lower charge.
*/
charge.current = 1500;
charge_manager_update(CHARGE_SUPPLIER_TEST7, 1, &charge);
wait_for_charge_manager_refresh();
TEST_ASSERT(active_charge_port == 1);
TEST_ASSERT(active_charge_limit == 1000);
/*
* Zero our HP charge and verify fallback to next highest priority,
* which happens to be a different port.
*/
charge.current = 0;
charge_manager_update(CHARGE_SUPPLIER_TEST2, 1, &charge);
wait_for_charge_manager_refresh();
TEST_ASSERT(active_charge_port == 0);
TEST_ASSERT(active_charge_limit == 2000);
/* Add a charge at equal priority and verify highest charge selected */
charge.current = 2500;
charge_manager_update(CHARGE_SUPPLIER_TEST5, 0, &charge);
wait_for_charge_manager_refresh();
TEST_ASSERT(active_charge_port == 0);
TEST_ASSERT(active_charge_limit == 2500);
charge.current = 3000;
charge_manager_update(CHARGE_SUPPLIER_TEST6, 1, &charge);
wait_for_charge_manager_refresh();
TEST_ASSERT(active_charge_port == 1);
TEST_ASSERT(active_charge_limit == 3000);
return EC_SUCCESS;
}
static int test_charge_ceil(void)
{
int port;
struct charge_port_info charge;
/* Initialize table to 1A @ 5V, and verify port + limit */
initialize_charge_table(1000, 5000, 1000);
TEST_ASSERT(active_charge_port != CHARGE_PORT_NONE);
TEST_ASSERT(active_charge_limit == 1000);
/* Set a 500mA ceiling, verify port is unchanged */
port = active_charge_port;
charge_manager_set_ceil(port, 500);
wait_for_charge_manager_refresh();
TEST_ASSERT(port == active_charge_port);
TEST_ASSERT(active_charge_limit == 500);
/* Raise the ceiling to 2A, verify limit goes back to 1A */
charge_manager_set_ceil(port, 2000);
wait_for_charge_manager_refresh();
TEST_ASSERT(port == active_charge_port);
TEST_ASSERT(active_charge_limit == 1000);
/* Verify that ceiling is ignored in determining active charge port */
charge.current = 2000;
charge.voltage = 5000;
charge_manager_update(0, 0, &charge);
charge.current = 2500;
charge_manager_update(0, 1, &charge);
charge_manager_set_ceil(1, 750);
wait_for_charge_manager_refresh();
TEST_ASSERT(active_charge_port == 1);
TEST_ASSERT(active_charge_limit == 750);
return EC_SUCCESS;
}
static int test_new_power_request(void)
{
struct charge_port_info charge;
/* Initialize table to no charge */
initialize_charge_table(0, 5000, 5000);
/* Clear power requests, and verify they are zero'd */
clear_new_power_requests();
wait_for_charge_manager_refresh();
TEST_ASSERT(new_power_request[0] == 0);
TEST_ASSERT(new_power_request[1] == 0);
/* Charge from port 1 and verify NPR on port 1 only */
charge.current = 1000;
charge.voltage = 5000;
charge_manager_update(CHARGE_SUPPLIER_TEST2, 1, &charge);
wait_for_charge_manager_refresh();
TEST_ASSERT(new_power_request[0] == 0);
TEST_ASSERT(new_power_request[1] == 1);
clear_new_power_requests();
/* Reduce port 1 limit and verify NPR on port 1 only */
charge_manager_set_ceil(1, 500);
wait_for_charge_manager_refresh();
TEST_ASSERT(new_power_request[0] == 0);
TEST_ASSERT(new_power_request[1] == 1);
clear_new_power_requests();
/* Add low-priority source and verify no NPRs */
charge_manager_update(CHARGE_SUPPLIER_TEST6, 0, &charge);
wait_for_charge_manager_refresh();
TEST_ASSERT(new_power_request[0] == 0);
TEST_ASSERT(new_power_request[1] == 0);
clear_new_power_requests();
/*
* Add higher-priority source and verify NPR on both ports,
* since we're switching charge ports.
*/
charge_manager_update(CHARGE_SUPPLIER_TEST1, 0, &charge);
wait_for_charge_manager_refresh();
TEST_ASSERT(new_power_request[0] == 1);
TEST_ASSERT(new_power_request[1] == 1);
clear_new_power_requests();
return EC_SUCCESS;
}
void run_test(void)
{
test_reset();
RUN_TEST(test_initialization);
RUN_TEST(test_priority);
RUN_TEST(test_charge_ceil);
RUN_TEST(test_new_power_request);
test_print_result();
}

View File

@@ -0,0 +1,17 @@
/* Copyright 2014 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.
*/
/**
* List of enabled tasks in the priority order
*
* The first one has the lowest priority.
*
* For each task, use the macro TASK_TEST(n, r, d, s) where :
* 'n' in the name of the task
* 'r' in the main routine of the task
* 'd' in an opaque parameter passed to the routine at startup
* 's' is the stack size in bytes; must be a multiple of 8
*/
#define CONFIG_TEST_TASK_LIST /* No test task */

View File

@@ -133,5 +133,10 @@ int board_discharge_on_ac(int enabled);
#define CONFIG_SW_CRC
#endif
#ifdef TEST_CHARGE_MANAGER
#define CONFIG_CHARGE_MANAGER
#define CONFIG_USB_PD_DUAL_ROLE
#endif
#endif /* TEST_BUILD */
#endif /* __CROS_EC_TEST_CONFIG_H */