summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShawn Nematbakhsh <shawnn@chromium.org>2014-11-05 10:02:01 -0800
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-11-13 00:29:58 +0000
commitcf48a3640c271663fc1c4156b16f4a25264944d9 (patch)
tree0330fdc3a2c6453bc46a4310431a1506bd978cfb
parent06fb4fe0f2ee33c912fa10ed7fecdbe8c9c193d6 (diff)
downloadchrome-ec-cf48a3640c271663fc1c4156b16f4a25264944d9.tar.gz
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>
-rw-r--r--board/host/board.h23
-rw-r--r--common/charge_manager.c2
-rw-r--r--test/build.mk3
-rw-r--r--test/charge_manager.c266
-rw-r--r--test/charge_manager.tasklist17
-rw-r--r--test/test_config.h5
6 files changed, 315 insertions, 1 deletions
diff --git a/board/host/board.h b/board/host/board.h
index 46d1a001b2..0ae8e0c452 100644
--- a/board/host/board.h
+++ b/board/host/board.h
@@ -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 */
diff --git a/common/charge_manager.c b/common/charge_manager.c
index 3cd3db2280..6926da4121 100644
--- a/common/charge_manager.c
+++ b/common/charge_manager.c
@@ -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 */
diff --git a/test/build.mk b/test/build.mk
index ff5e617fbb..0515d5a142 100644
--- a/test/build.mk
+++ b/test/build.mk
@@ -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
diff --git a/test/charge_manager.c b/test/charge_manager.c
new file mode 100644
index 0000000000..b721d79e52
--- /dev/null
+++ b/test/charge_manager.c
@@ -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();
+}
diff --git a/test/charge_manager.tasklist b/test/charge_manager.tasklist
new file mode 100644
index 0000000000..927bd24ee1
--- /dev/null
+++ b/test/charge_manager.tasklist
@@ -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 */
diff --git a/test/test_config.h b/test/test_config.h
index 303bc54f86..2fd090d5d0 100644
--- a/test/test_config.h
+++ b/test/test_config.h
@@ -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 */