blob: fbc791959911d5c7c47d4f832272982b2185d340 [file] [log] [blame]
/* Copyright 2019 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.
*/
/* These unit tests are designed to test probing from multiple
platforms. CONFIG_SINGLE_PLATFORM should not be enabled. */
#undef CONFIG_SINGLE_PLATFORM
#include <limits.h>
#include <setjmp.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
// cmocka doesn't include some headers it uses, e.g. setjmp. Prevent
// clang-format from putting the headers in order, so it gets the above
// includes.
// clang-format off
#include <cmocka.h>
// clang-format on
#include "mosys/globals.h"
#include "mosys/intf_list.h"
#include "mosys/platform.h"
/* Subcommands list used for testing which defines no commands */
static struct platform_cmd *no_subcommands[] = {
NULL
};
/* Test probe functions, which records what they are called on */
static struct platform_intf *probe_called;
static int probe_never_match(struct platform_intf *intf)
{
probe_called = intf;
return 0;
}
static bool probe_mocked_match_enable;
static int probe_mocked_match(struct platform_intf *intf)
{
probe_called = intf;
return probe_mocked_match_enable;
}
static int probe_always_error(struct platform_intf *intf)
{
probe_called = intf;
return -1;
}
/* Test setup functions, which records what they are called on */
static struct platform_intf *setup_called;
static int setup_always_success(struct platform_intf *intf)
{
setup_called = intf;
return 0;
}
static int setup_always_error(struct platform_intf *intf)
{
setup_called = intf;
return -1;
}
/* Test destroy function, which records what it was called on */
static struct platform_intf *destroy_called;
static int destroy(struct platform_intf *intf)
{
destroy_called = intf;
return 0;
}
/* Test setup-post functions, which records what they are called on */
static struct platform_intf *setup_post_called;
static int setup_post_always_success(struct platform_intf *intf)
{
setup_post_called = intf;
return 0;
}
static int setup_post_always_error(struct platform_intf *intf)
{
setup_post_called = intf;
return -1;
}
/*
* A minimal platform intf definition that should match by name, but
* not call any probe, setup, destroy, or setup-post functions.
*/
static struct platform_intf minimal_intf;
REGISTER_PLATFORM(minimal_intf, "minimal");
/*
* A more complete definition which should never match, but may probe,
* setup, destroy, or setup-post without error.
*/
static struct platform_intf basic_intf = {
.type = PLATFORM_X86_64,
.sub = no_subcommands,
.probe = &probe_never_match,
.setup = &setup_always_success,
.destroy = &destroy,
.setup_post = &setup_post_always_success,
};
REGISTER_PLATFORM(basic_intf, "basic");
/*
* Same as basic, but always errors during probing
*/
static struct platform_intf error_probe_intf = {
.type = PLATFORM_X86_64,
.sub = no_subcommands,
.probe = &probe_always_error,
.setup = &setup_always_success,
.destroy = &destroy,
.setup_post = &setup_post_always_success,
};
REGISTER_PLATFORM(error_probe_intf, "error_probe");
/*
* Same as basic, but always errors during setup
*/
static struct platform_intf error_setup_intf = {
.type = PLATFORM_X86_64,
.sub = no_subcommands,
.probe = &probe_never_match,
.setup = &setup_always_error,
.destroy = &destroy,
.setup_post = &setup_post_always_success,
};
REGISTER_PLATFORM(error_setup_intf, "error_setup");
/*
* Same as basic, but always errors during setup-post
*/
static struct platform_intf error_setup_post_intf = {
.type = PLATFORM_X86_64,
.sub = no_subcommands,
.probe = &probe_never_match,
.setup = &setup_always_success,
.destroy = &destroy,
.setup_post = &setup_post_always_error,
};
REGISTER_PLATFORM(error_setup_post_intf, "error_setup_post");
/*
* Same as error_setup_post, but always errors during setup-post
*/
static struct platform_intf error_setup_post_no_destroy_intf = {
.type = PLATFORM_X86_64,
.sub = no_subcommands,
.probe = &probe_never_match,
.setup = &setup_always_success,
.setup_post = &setup_post_always_error,
};
REGISTER_PLATFORM(error_setup_post_no_destroy_intf,
"error_setup_post_no_destroy");
/*
* Same as basic, but matches conditionally during probing based on
* the probe_mocked_match_enable variable.
*/
static struct platform_intf mocked_match_intf = {
.type = PLATFORM_X86_64,
.sub = no_subcommands,
.probe = &probe_mocked_match,
.setup = &setup_always_success,
.destroy = &destroy,
.setup_post = &setup_post_always_success,
};
REGISTER_PLATFORM(mocked_match_intf, "mocked_match");
static void find_minimal_by_name(void **state)
{
assert_ptr_equal(mosys_platform_setup("minimal"), &minimal_intf);
assert_null(probe_called);
assert_null(setup_called);
assert_null(destroy_called);
assert_null(setup_post_called);
}
static void find_basic_by_name(void **state)
{
assert_ptr_equal(mosys_platform_setup("basic"), &basic_intf);
assert_ptr_equal(probe_called, &basic_intf);
assert_ptr_equal(setup_called, &basic_intf);
assert_null(destroy_called);
assert_ptr_equal(setup_post_called, &basic_intf);
probe_called = NULL;
setup_called = NULL;
setup_post_called = NULL;
}
static void find_by_name_is_case_insensitive(void **state)
{
assert_ptr_equal(mosys_platform_setup("BaSiC"), &basic_intf);
assert_ptr_equal(probe_called, &basic_intf);
assert_ptr_equal(setup_called, &basic_intf);
assert_null(destroy_called);
assert_ptr_equal(setup_post_called, &basic_intf);
probe_called = NULL;
setup_called = NULL;
setup_post_called = NULL;
}
static void find_bad_name_fails(void **state)
{
assert_null(mosys_platform_setup("BAD~NAME"));
assert_null(probe_called);
assert_null(setup_called);
assert_null(destroy_called);
assert_null(setup_post_called);
}
static void setup_error_fails(void **state)
{
assert_null(mosys_platform_setup("error_setup"));
assert_ptr_equal(probe_called, &error_setup_intf);
assert_ptr_equal(setup_called, &error_setup_intf);
assert_null(destroy_called);
assert_null(setup_post_called);
probe_called = NULL;
setup_called = NULL;
destroy_called = NULL;
}
static void setup_post_error_fails(void **state)
{
assert_null(mosys_platform_setup("error_setup_post"));
assert_ptr_equal(probe_called, &error_setup_post_intf);
assert_ptr_equal(setup_called, &error_setup_post_intf);
assert_ptr_equal(destroy_called, &error_setup_post_intf);
assert_ptr_equal(setup_post_called, &error_setup_post_intf);
probe_called = NULL;
setup_called = NULL;
destroy_called = NULL;
setup_post_called = NULL;
}
static void setup_post_error_fails_no_destroy(void **state)
{
assert_null(mosys_platform_setup("error_setup_post_no_destroy"));
assert_ptr_equal(probe_called, &error_setup_post_no_destroy_intf);
assert_ptr_equal(setup_called, &error_setup_post_no_destroy_intf);
assert_null(destroy_called);
assert_ptr_equal(setup_post_called, &error_setup_post_no_destroy_intf);
probe_called = NULL;
setup_called = NULL;
setup_post_called = NULL;
}
static void probe_matches(void **state)
{
probe_mocked_match_enable = true;
assert_ptr_equal(mosys_platform_setup(NULL), &mocked_match_intf);
assert_ptr_equal(probe_called, &mocked_match_intf);
assert_ptr_equal(setup_called, &mocked_match_intf);
assert_null(destroy_called);
assert_ptr_equal(setup_post_called, &mocked_match_intf);
probe_called = NULL;
setup_called = NULL;
setup_post_called = NULL;
probe_mocked_match_enable = false;
}
static void probe_fails(void **state)
{
assert_null(mosys_platform_setup(NULL));
assert_non_null(probe_called);
assert_null(setup_called);
assert_null(destroy_called);
assert_null(setup_post_called);
probe_called = NULL;
}
int main(void)
{
const struct CMUnitTest tests[] = {
cmocka_unit_test(find_minimal_by_name),
cmocka_unit_test(find_basic_by_name),
cmocka_unit_test(find_by_name_is_case_insensitive),
cmocka_unit_test(find_bad_name_fails),
cmocka_unit_test(setup_error_fails),
cmocka_unit_test(setup_post_error_fails),
cmocka_unit_test(setup_post_error_fails_no_destroy),
cmocka_unit_test(probe_matches),
cmocka_unit_test(probe_fails),
};
return cmocka_run_group_tests(tests, NULL, NULL);
}