blob: e23906ec80fe336257c0b5c7c14c6f7e081628a7 [file] [log] [blame]
// Copyright 2016 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 <gtest/gtest.h>
#include <stdio.h>
#include <vector>
extern "C" {
#include "cras_main_message.h"
#include "cras_rstream.h"
#include "cras_server_metrics.c"
}
static enum CRAS_MAIN_MESSAGE_TYPE type_set;
static struct timespec clock_gettime_retspec;
std::vector<struct cras_server_metrics_message> sent_msgs;
void ResetStubData() {
type_set = (enum CRAS_MAIN_MESSAGE_TYPE)0;
sent_msgs.clear();
}
namespace {
TEST(ServerMetricsTestSuite, Init) {
ResetStubData();
cras_server_metrics_init();
EXPECT_EQ(type_set, CRAS_MAIN_METRICS);
}
TEST(ServerMetricsTestSuite, SetMetricsDeviceRuntime) {
ResetStubData();
struct cras_iodev iodev;
struct cras_ionode active_node;
clock_gettime_retspec.tv_sec = 200;
clock_gettime_retspec.tv_nsec = 0;
iodev.info.idx = MAX_SPECIAL_DEVICE_IDX;
iodev.open_ts.tv_sec = 100;
iodev.open_ts.tv_nsec = 0;
iodev.direction = CRAS_STREAM_INPUT;
iodev.active_node = &active_node;
active_node.type = CRAS_NODE_TYPE_USB;
cras_server_metrics_device_runtime(&iodev);
EXPECT_EQ(sent_msgs.size(), 1);
EXPECT_EQ(sent_msgs[0].header.type, CRAS_MAIN_METRICS);
EXPECT_EQ(sent_msgs[0].header.length,
sizeof(struct cras_server_metrics_message));
EXPECT_EQ(sent_msgs[0].metrics_type, DEVICE_RUNTIME);
EXPECT_EQ(sent_msgs[0].data.device_data.type, CRAS_METRICS_DEVICE_USB);
EXPECT_EQ(sent_msgs[0].data.device_data.direction, CRAS_STREAM_INPUT);
EXPECT_EQ(sent_msgs[0].data.device_data.runtime.tv_sec, 100);
sent_msgs.clear();
clock_gettime_retspec.tv_sec = 300;
clock_gettime_retspec.tv_nsec = 0;
iodev.open_ts.tv_sec = 100;
iodev.open_ts.tv_nsec = 0;
iodev.direction = CRAS_STREAM_OUTPUT;
iodev.active_node = &active_node;
active_node.type = CRAS_NODE_TYPE_HEADPHONE;
cras_server_metrics_device_runtime(&iodev);
EXPECT_EQ(sent_msgs.size(), 1);
EXPECT_EQ(sent_msgs[0].header.type, CRAS_MAIN_METRICS);
EXPECT_EQ(sent_msgs[0].header.length,
sizeof(struct cras_server_metrics_message));
EXPECT_EQ(sent_msgs[0].metrics_type, DEVICE_RUNTIME);
EXPECT_EQ(sent_msgs[0].data.device_data.type, CRAS_METRICS_DEVICE_HEADPHONE);
EXPECT_EQ(sent_msgs[0].data.device_data.direction, CRAS_STREAM_OUTPUT);
EXPECT_EQ(sent_msgs[0].data.device_data.runtime.tv_sec, 200);
}
TEST(ServerMetricsTestSuite, SetMetricsHighestDeviceDelay) {
ResetStubData();
unsigned int hw_level = 1000;
unsigned int largest_cb_level = 500;
cras_server_metrics_highest_device_delay(hw_level, largest_cb_level,
CRAS_STREAM_INPUT);
EXPECT_EQ(sent_msgs.size(), 1);
EXPECT_EQ(sent_msgs[0].header.type, CRAS_MAIN_METRICS);
EXPECT_EQ(sent_msgs[0].header.length,
sizeof(struct cras_server_metrics_message));
EXPECT_EQ(sent_msgs[0].metrics_type, HIGHEST_DEVICE_DELAY_INPUT);
EXPECT_EQ(sent_msgs[0].data.value, 2000);
sent_msgs.clear();
cras_server_metrics_highest_device_delay(hw_level, largest_cb_level,
CRAS_STREAM_OUTPUT);
EXPECT_EQ(sent_msgs.size(), 1);
EXPECT_EQ(sent_msgs[0].header.type, CRAS_MAIN_METRICS);
EXPECT_EQ(sent_msgs[0].header.length,
sizeof(struct cras_server_metrics_message));
EXPECT_EQ(sent_msgs[0].metrics_type, HIGHEST_DEVICE_DELAY_OUTPUT);
EXPECT_EQ(sent_msgs[0].data.value, 2000);
}
TEST(ServerMetricsTestSuite, SetMetricHighestHardwareLevel) {
ResetStubData();
unsigned int hw_level = 1000;
cras_server_metrics_highest_hw_level(hw_level, CRAS_STREAM_INPUT);
EXPECT_EQ(sent_msgs.size(), 1);
EXPECT_EQ(sent_msgs[0].header.type, CRAS_MAIN_METRICS);
EXPECT_EQ(sent_msgs[0].header.length,
sizeof(struct cras_server_metrics_message));
EXPECT_EQ(sent_msgs[0].metrics_type, HIGHEST_INPUT_HW_LEVEL);
EXPECT_EQ(sent_msgs[0].data.value, hw_level);
sent_msgs.clear();
cras_server_metrics_highest_hw_level(hw_level, CRAS_STREAM_OUTPUT);
EXPECT_EQ(sent_msgs.size(), 1);
EXPECT_EQ(sent_msgs[0].header.type, CRAS_MAIN_METRICS);
EXPECT_EQ(sent_msgs[0].header.length,
sizeof(struct cras_server_metrics_message));
EXPECT_EQ(sent_msgs[0].metrics_type, HIGHEST_OUTPUT_HW_LEVEL);
EXPECT_EQ(sent_msgs[0].data.value, hw_level);
}
TEST(ServerMetricsTestSuite, SetMetricsNumUnderruns) {
ResetStubData();
unsigned int underrun = 10;
cras_server_metrics_num_underruns(underrun);
EXPECT_EQ(sent_msgs.size(), 1);
EXPECT_EQ(sent_msgs[0].header.type, CRAS_MAIN_METRICS);
EXPECT_EQ(sent_msgs[0].header.length,
sizeof(struct cras_server_metrics_message));
EXPECT_EQ(sent_msgs[0].metrics_type, NUM_UNDERRUNS);
EXPECT_EQ(sent_msgs[0].data.value, underrun);
}
TEST(ServerMetricsTestSuite, SetMetricsMissedCallbackEventInputStream) {
ResetStubData();
struct cras_rstream stream;
struct timespec diff_ts;
stream.flags = 0;
stream.start_ts.tv_sec = 0;
stream.start_ts.tv_nsec = 0;
stream.num_missed_cb = 0;
stream.direction = CRAS_STREAM_INPUT;
clock_gettime_retspec.tv_sec = 100;
clock_gettime_retspec.tv_nsec = 0;
cras_server_metrics_missed_cb_event(&stream);
subtract_timespecs(&clock_gettime_retspec, &stream.start_ts, &diff_ts);
EXPECT_EQ(sent_msgs.size(), 1);
EXPECT_EQ(sent_msgs[0].header.type, CRAS_MAIN_METRICS);
EXPECT_EQ(sent_msgs[0].header.length,
sizeof(struct cras_server_metrics_message));
EXPECT_EQ(sent_msgs[0].metrics_type, MISSED_CB_FIRST_TIME_INPUT);
EXPECT_EQ(sent_msgs[0].data.value, diff_ts.tv_sec);
EXPECT_EQ(stream.num_missed_cb, 1);
EXPECT_EQ(stream.first_missed_cb_ts.tv_sec, clock_gettime_retspec.tv_sec);
EXPECT_EQ(stream.first_missed_cb_ts.tv_nsec, clock_gettime_retspec.tv_nsec);
clock_gettime_retspec.tv_sec = 200;
clock_gettime_retspec.tv_nsec = 0;
cras_server_metrics_missed_cb_event(&stream);
subtract_timespecs(&clock_gettime_retspec, &stream.first_missed_cb_ts,
&diff_ts);
EXPECT_EQ(sent_msgs.size(), 2);
EXPECT_EQ(sent_msgs[1].header.type, CRAS_MAIN_METRICS);
EXPECT_EQ(sent_msgs[1].header.length,
sizeof(struct cras_server_metrics_message));
EXPECT_EQ(sent_msgs[1].metrics_type, MISSED_CB_SECOND_TIME_INPUT);
EXPECT_EQ(sent_msgs[1].data.value, diff_ts.tv_sec);
EXPECT_EQ(stream.num_missed_cb, 2);
}
TEST(ServerMetricsTestSuite, SetMetricsMissedCallbackEventOutputStream) {
ResetStubData();
struct cras_rstream stream;
struct timespec diff_ts;
stream.flags = 0;
stream.start_ts.tv_sec = 0;
stream.start_ts.tv_nsec = 0;
stream.num_missed_cb = 0;
stream.direction = CRAS_STREAM_OUTPUT;
clock_gettime_retspec.tv_sec = 100;
clock_gettime_retspec.tv_nsec = 0;
cras_server_metrics_missed_cb_event(&stream);
subtract_timespecs(&clock_gettime_retspec, &stream.start_ts, &diff_ts);
EXPECT_EQ(sent_msgs.size(), 1);
EXPECT_EQ(sent_msgs[0].header.type, CRAS_MAIN_METRICS);
EXPECT_EQ(sent_msgs[0].header.length,
sizeof(struct cras_server_metrics_message));
EXPECT_EQ(sent_msgs[0].metrics_type, MISSED_CB_FIRST_TIME_OUTPUT);
EXPECT_EQ(sent_msgs[0].data.value, diff_ts.tv_sec);
EXPECT_EQ(stream.num_missed_cb, 1);
EXPECT_EQ(stream.first_missed_cb_ts.tv_sec, clock_gettime_retspec.tv_sec);
EXPECT_EQ(stream.first_missed_cb_ts.tv_nsec, clock_gettime_retspec.tv_nsec);
clock_gettime_retspec.tv_sec = 200;
clock_gettime_retspec.tv_nsec = 0;
cras_server_metrics_missed_cb_event(&stream);
subtract_timespecs(&clock_gettime_retspec, &stream.first_missed_cb_ts,
&diff_ts);
EXPECT_EQ(sent_msgs.size(), 2);
EXPECT_EQ(sent_msgs[1].header.type, CRAS_MAIN_METRICS);
EXPECT_EQ(sent_msgs[1].header.length,
sizeof(struct cras_server_metrics_message));
EXPECT_EQ(sent_msgs[1].metrics_type, MISSED_CB_SECOND_TIME_OUTPUT);
EXPECT_EQ(sent_msgs[1].data.value, diff_ts.tv_sec);
EXPECT_EQ(stream.num_missed_cb, 2);
}
TEST(ServerMetricsTestSuite, SetMetricsStreamCreate) {
ResetStubData();
struct cras_rstream_config config;
struct cras_audio_format format;
config.direction = CRAS_STREAM_INPUT;
config.cb_threshold = 1024;
config.flags = BULK_AUDIO_OK;
format.format = SND_PCM_FORMAT_S16_LE;
format.frame_rate = 48000;
config.client_type = CRAS_CLIENT_TYPE_TEST;
config.format = &format;
cras_server_metrics_stream_create(&config);
// Log stream config.
EXPECT_EQ(sent_msgs.size(), 1);
EXPECT_EQ(sent_msgs[0].header.type, CRAS_MAIN_METRICS);
EXPECT_EQ(sent_msgs[0].header.length,
sizeof(struct cras_server_metrics_message));
EXPECT_EQ(sent_msgs[0].metrics_type, STREAM_CONFIG);
EXPECT_EQ(sent_msgs[0].data.stream_config.direction, CRAS_STREAM_INPUT);
EXPECT_EQ(sent_msgs[0].data.stream_config.cb_threshold, 1024);
EXPECT_EQ(sent_msgs[0].data.stream_config.flags, BULK_AUDIO_OK);
EXPECT_EQ(sent_msgs[0].data.stream_config.format, SND_PCM_FORMAT_S16_LE);
EXPECT_EQ(sent_msgs[0].data.stream_config.rate, 48000);
EXPECT_EQ(sent_msgs[0].data.stream_config.client_type, CRAS_CLIENT_TYPE_TEST);
}
TEST(ServerMetricsTestSuite, SetMetricsStreamDestroy) {
ResetStubData();
struct cras_rstream stream;
struct timespec diff_ts;
stream.flags = 0;
stream.start_ts.tv_sec = 0;
stream.start_ts.tv_nsec = 0;
clock_gettime_retspec.tv_sec = 1000;
clock_gettime_retspec.tv_nsec = 0;
stream.num_missed_cb = 5;
stream.first_missed_cb_ts.tv_sec = 100;
stream.first_missed_cb_ts.tv_nsec = 0;
stream.longest_fetch_interval.tv_sec = 1;
stream.longest_fetch_interval.tv_nsec = 0;
stream.sleep_interval_ts.tv_sec = 0;
stream.sleep_interval_ts.tv_nsec = 5000000;
stream.direction = CRAS_STREAM_INPUT;
stream.client_type = CRAS_CLIENT_TYPE_TEST;
stream.stream_type = CRAS_STREAM_TYPE_DEFAULT;
cras_server_metrics_stream_destroy(&stream);
subtract_timespecs(&clock_gettime_retspec, &stream.start_ts, &diff_ts);
EXPECT_EQ(sent_msgs.size(), 4);
// Log missed cb frequency.
EXPECT_EQ(sent_msgs[0].header.type, CRAS_MAIN_METRICS);
EXPECT_EQ(sent_msgs[0].header.length,
sizeof(struct cras_server_metrics_message));
EXPECT_EQ(sent_msgs[0].metrics_type, MISSED_CB_FREQUENCY_INPUT);
EXPECT_EQ(sent_msgs[0].data.value,
stream.num_missed_cb * 86400 / diff_ts.tv_sec);
// Log missed cb frequency after rescheduling.
subtract_timespecs(&clock_gettime_retspec, &stream.first_missed_cb_ts,
&diff_ts);
EXPECT_EQ(sent_msgs[1].header.type, CRAS_MAIN_METRICS);
EXPECT_EQ(sent_msgs[1].header.length,
sizeof(struct cras_server_metrics_message));
EXPECT_EQ(sent_msgs[1].metrics_type,
MISSED_CB_FREQUENCY_AFTER_RESCHEDULING_INPUT);
EXPECT_EQ(sent_msgs[1].data.value,
(stream.num_missed_cb - 1) * 86400 / diff_ts.tv_sec);
// Log stream runtime.
EXPECT_EQ(sent_msgs[2].header.type, CRAS_MAIN_METRICS);
EXPECT_EQ(sent_msgs[2].header.length,
sizeof(struct cras_server_metrics_message));
EXPECT_EQ(sent_msgs[2].metrics_type, STREAM_RUNTIME);
EXPECT_EQ(sent_msgs[2].data.stream_data.client_type, CRAS_CLIENT_TYPE_TEST);
EXPECT_EQ(sent_msgs[2].data.stream_data.stream_type,
CRAS_STREAM_TYPE_DEFAULT);
EXPECT_EQ(sent_msgs[2].data.stream_data.direction, CRAS_STREAM_INPUT);
EXPECT_EQ(sent_msgs[2].data.stream_data.runtime.tv_sec, 1000);
// Log longest fetch delay.
EXPECT_EQ(sent_msgs[3].header.type, CRAS_MAIN_METRICS);
EXPECT_EQ(sent_msgs[3].header.length,
sizeof(struct cras_server_metrics_message));
EXPECT_EQ(sent_msgs[3].metrics_type, LONGEST_FETCH_DELAY);
EXPECT_EQ(sent_msgs[3].data.stream_data.client_type, CRAS_CLIENT_TYPE_TEST);
EXPECT_EQ(sent_msgs[3].data.stream_data.stream_type,
CRAS_STREAM_TYPE_DEFAULT);
EXPECT_EQ(sent_msgs[3].data.stream_data.direction, CRAS_STREAM_INPUT);
EXPECT_EQ(sent_msgs[3].data.stream_data.runtime.tv_sec, 0);
EXPECT_EQ(sent_msgs[3].data.stream_data.runtime.tv_nsec, 995000000);
}
TEST(ServerMetricsTestSuite, SetMetricsBusyloop) {
ResetStubData();
struct timespec time = {40, 0};
unsigned count = 3;
cras_server_metrics_busyloop(&time, count);
EXPECT_EQ(sent_msgs.size(), 1);
EXPECT_EQ(sent_msgs[0].header.type, CRAS_MAIN_METRICS);
EXPECT_EQ(sent_msgs[0].header.length,
sizeof(struct cras_server_metrics_message));
EXPECT_EQ(sent_msgs[0].metrics_type, BUSYLOOP);
EXPECT_EQ(sent_msgs[0].data.timespec_data.runtime.tv_sec, 40);
EXPECT_EQ(sent_msgs[0].data.timespec_data.runtime.tv_nsec, 0);
EXPECT_EQ(sent_msgs[0].data.timespec_data.count, 3);
}
TEST(ServerMetricsTestSuite, SetMetricsBusyloopLength) {
ResetStubData();
unsigned length = 5;
cras_server_metrics_busyloop_length(length);
EXPECT_EQ(sent_msgs.size(), 1);
EXPECT_EQ(sent_msgs[0].header.type, CRAS_MAIN_METRICS);
EXPECT_EQ(sent_msgs[0].header.length,
sizeof(struct cras_server_metrics_message));
EXPECT_EQ(sent_msgs[0].metrics_type, BUSYLOOP_LENGTH);
EXPECT_EQ(sent_msgs[0].data.value, 5);
}
extern "C" {
int cras_main_message_add_handler(enum CRAS_MAIN_MESSAGE_TYPE type,
cras_message_callback callback,
void* callback_data) {
type_set = type;
return 0;
}
void cras_metrics_log_histogram(const char* name,
int sample,
int min,
int max,
int nbuckets) {}
void cras_metrics_log_sparse_histogram(const char* name, int sample) {}
int cras_main_message_send(struct cras_main_message* msg) {
// Copy the sent message so we can examine it in the test later.
struct cras_server_metrics_message sent_msg;
memcpy(&sent_msg, msg, sizeof(sent_msg));
sent_msgs.push_back(sent_msg);
return 0;
}
int cras_system_state_in_main_thread() {
return 0;
}
// From librt.
int clock_gettime(clockid_t clk_id, struct timespec* tp) {
tp->tv_sec = clock_gettime_retspec.tv_sec;
tp->tv_nsec = clock_gettime_retspec.tv_nsec;
return 0;
}
} // extern "C"
} // namespace
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
int rc = RUN_ALL_TESTS();
return rc;
}