From: Kichan Kwon Date: Wed, 12 Jul 2017 07:40:16 +0000 (+0900) Subject: Make unit test X-Git-Tag: accepted/tizen/4.0/unified/20170816.011237~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=fa9cd2013de495025a1ca5a6b9a9cc51649cf493;p=platform%2Fcore%2Fapi%2Fruntime-info.git Make unit test - Existed TCs just check sanity - This test read system data directly and compare with runtime-info result Change-Id: I749bdad919f17c12ac6e5f7f395fd640016bb1d0 Signed-off-by: Kichan Kwon --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 6cb90fc..653911a 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ SET(PREFIX ${CMAKE_INSTALL_PREFIX}) SET(INC_DIR include) INCLUDE_DIRECTORIES(${INC_DIR}) -SET(requires "dlog vconf capi-base-common capi-system-info") +SET(requires "dlog vconf capi-base-common capi-system-info glib-2.0 gio-2.0") SET(pc_requires "capi-base-common") INCLUDE(FindPkgConfig) @@ -67,10 +67,10 @@ IF(UNIX) ADD_CUSTOM_TARGET (distclean @echo cleaning for source distribution) ADD_CUSTOM_COMMAND( - DEPENDS clean + DEPENDS clean COMMENT "distribution clean" COMMAND find - ARGS . + ARGS . -not -name config.cmake -and \( -name tester.c -or -name Testing -or @@ -94,3 +94,8 @@ ADD_CUSTOM_COMMAND( ENDIF(UNIX) +SET(TEST_NAME "runtime-info-test") +aux_source_directory(test TEST_SOURCES) +ADD_EXECUTABLE(${TEST_NAME} ${TEST_SOURCES}) +TARGET_LINK_LIBRARIES(${TEST_NAME} ${${fw_name}_LDFLAGS} ${fw_name}) +INSTALL(TARGETS ${TEST_NAME} DESTINATION bin) diff --git a/packaging/capi-system-runtime-info.spec b/packaging/capi-system-runtime-info.spec index 3abbda8..e219f78 100644 --- a/packaging/capi-system-runtime-info.spec +++ b/packaging/capi-system-runtime-info.spec @@ -12,6 +12,7 @@ BuildRequires: pkgconfig(dlog) BuildRequires: pkgconfig(vconf) BuildRequires: pkgconfig(capi-base-common) BuildRequires: pkgconfig(capi-system-info) +BuildRequires: pkgconfig(glib-2.0) Requires(post): /sbin/ldconfig Requires(postun): /sbin/ldconfig @@ -28,6 +29,13 @@ Requires: pkgconfig(capi-base-common) %devel_desc +%package test +Summary: A Runtime Information test binary +Requires: %{name} = %{version}-%{release} + +%description test +Binary for testing Runtime-info APIs + %prep %setup -q @@ -58,4 +66,5 @@ make %{?jobs:-j%jobs} %{_libdir}/pkgconfig/*.pc %{_libdir}/lib*.so - +%files test +%attr(700,root,root) %{_bindir}/runtime-info-test diff --git a/test/runtime_info_test.c b/test/runtime_info_test.c new file mode 100644 index 0000000..1b66abf --- /dev/null +++ b/test/runtime_info_test.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2011 - 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include + +#include + +#include "runtime_info_test.h" + +static pid_t fork_child(void) +{ + int i, sum; + pid_t pid; + + pid = fork(); + + switch (pid) { + case -1: + printf("Failed to fork child process (%d)\n", errno); + return -1; + case 0: + while (true) { + /* + * This calculation is meaningless. + * Just for increasing utime to test getting CPU time. + */ + sum = 0; + for (i = 0; i < 1000000; i++) + sum = (i % 2) ? sum + i : sum - i; + sum /= 2; + sleep(1); + } + return -1; + default: + return pid; + } +} + +/* max_err : allowed max error (percent) */ +int check_value(int val1, int val2, int max_err) +{ + double div; + double max_err_percent = max_err / 100.0; + + if (val2 == 0) { + if (val1 != 0) { + printf("Incorrect value : runtime-info(%d), expected(%d)\n", val1, val2); + return FAIL; + } + + return SUCCESS; + } + + div = (double)val1 / val2; + if (div > 1 + max_err_percent || div < 1 - max_err_percent) { + printf("Incorrect value : runtime-info(%d), expected(%d)\n", val1, val2); + return FAIL; + } + + return SUCCESS; +} + +int main(void) +{ + printf("=====================================================\n"); + printf(" Runtime-info test program\n"); + printf("=====================================================\n\n"); + + pid_t pid = fork_child(); + if (pid < 0) { + printf("Failed to fork test process\n"); + return 1; + } + + runtime_info_test_get_value_bool(); PRINT_LINE; + runtime_info_test_get_value_int(); PRINT_LINE; + runtime_info_test_set_changed_cb(); PRINT_LINE; + runtime_info_test_get_system_memory_info(); PRINT_LINE; + runtime_info_test_get_cpu_usage(); PRINT_LINE; + runtime_info_test_get_physical_memory_size(); PRINT_LINE; + runtime_info_test_get_process_memory_info(pid); PRINT_LINE; + runtime_info_test_get_process_cpu_usage(pid); PRINT_LINE; + runtime_info_test_get_all_apps_memory_usage(); PRINT_LINE; + runtime_info_test_get_all_apps_cpu_rate(); PRINT_LINE; + runtime_info_test_get_processor_count(); PRINT_LINE; + runtime_info_test_get_processor_current_frequency(); PRINT_LINE; + runtime_info_test_get_processor_max_frequency(); PRINT_LINE; + + kill(pid, SIGKILL); + + return 0; +} diff --git a/test/runtime_info_test.h b/test/runtime_info_test.h new file mode 100644 index 0000000..90a5742 --- /dev/null +++ b/test/runtime_info_test.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2011 - 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __RUNTIME_INFO_TEST_H__ +#define __RUNTIME_INFO_TEST_H__ + +#include + +#define BUF_SIZE 1024 + +enum test_result { + SUCCESS, + FAIL, + ERROR, + NOT_SUPPORTED, +}; + +#define PRINT_RESULT(result) ((result) == SUCCESS) ? "\x1b[32mSUCCESS\x1b[0m" : (((result) == FAIL) ? "\x1b[31mFAIL\x1b[0m" : (((result) == ERROR) ? "\x1b[31mERROR\x1b[0m" : (((result) == NOT_SUPPORTED) ? "\x1b[34mNOT SUPPORTED\x1b[0m" : NULL))) +#define PRINT_LINE printf("\n-----------------------------------------------------\n\n"); +#define PRINT_NOTICE(msg) printf("\x1b[33mNOTICE : %s\x1b[0m\n", msg); + +/* Compare two values and judge */ +int check_value(int val1, int val2, int max_err); + +/* Vconf related TCs */ +void runtime_info_test_get_value_bool(void); +void runtime_info_test_get_value_int(void); +void runtime_info_test_set_changed_cb(void); + +/* /proc related TCs */ +void runtime_info_test_get_system_memory_info(void); +void runtime_info_test_get_cpu_usage(void); +void runtime_info_test_get_physical_memory_size(void); + +/* Resourced related TCs */ +void runtime_info_test_get_process_memory_info(pid_t pid); +void runtime_info_test_get_process_cpu_usage(pid_t pid); +void runtime_info_test_get_all_apps_memory_usage(void); +void runtime_info_test_get_all_apps_cpu_rate(void); + +/* /sys/devices (CPU) related TCs */ +void runtime_info_test_get_processor_count(void); +void runtime_info_test_get_processor_current_frequency(void); +void runtime_info_test_get_processor_max_frequency(void); + +#endif /* __RUNTIME_INFO_TEST_H__ */ diff --git a/test/runtime_info_test_devices.c b/test/runtime_info_test_devices.c new file mode 100644 index 0000000..c575e47 --- /dev/null +++ b/test/runtime_info_test_devices.c @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2011 - 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include + +#include "runtime_info_test.h" + +#define CPU_CORE_FILE "/sys/devices/system/cpu/possible" +#define CUR_FREQ_FILE "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq" +#define MAX_FREQ_FILE "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq" +#define CPUINFO_FILE "/proc/cpuinfo" + +enum freq_type { + CUR, + MAX, +}; + +void runtime_info_test_get_processor_count(void) +{ + int ret; + int num_core_r; + FILE *fp; + unsigned int from, to; + long long num_core; + + printf("Runtime_info_get_processor_count test\n"); + + ret = runtime_info_get_processor_count(&num_core_r); + if (ret) { + printf("runtime_info_get_processor_count failed (%d)\n", ret); + printf(" Result : %s\n", PRINT_RESULT(ERROR)); + return; + } + + fp = fopen(CPU_CORE_FILE, "r"); + if (!fp) { + printf("Failed to open %s\n", CPU_CORE_FILE); + printf(" Result : %s\n", PRINT_RESULT(ERROR)); + return; + } + + if (!fscanf(fp, "%u-%u", &from, &to)) { + printf("%s has invalid format\n", CPU_CORE_FILE); + printf(" Result : %s\n", PRINT_RESULT(ERROR)); + fclose(fp); + return; + } + + if (to >= from) + num_core = (long long)to - from + 1; + else + num_core = 0; + + fclose(fp); + + printf(" The number of CPU core : %s\n", + PRINT_RESULT(check_value(num_core_r, num_core, 0))); +} + +static void runtime_info_test_helper_get_processor_frequency( + char *api_name, char *freq_file_name, int type) +{ + int ret; + int cpu_freq; + FILE *fp; + int freq; + char buf[BUF_SIZE]; + char *start; + + printf("%s test\n", api_name); + + if (type == CUR) + ret = runtime_info_get_processor_current_frequency(0, &cpu_freq); + else + ret = runtime_info_get_processor_max_frequency(0, &cpu_freq); + if (ret) { + printf("%s failed (%d)\n\n", api_name, ret); + printf(" Result : %s\n", PRINT_RESULT(ERROR)); + return; + } + + if (access(freq_file_name, F_OK) == 0) { + fp = fopen(freq_file_name, "r"); + if (!fp) { + printf("Failed to open %s\n", freq_file_name); + printf(" Result : %s\n", PRINT_RESULT(ERROR)); + return; + } + + if (!fscanf(fp, "%d", &freq)) { + printf("%s has invalid format\n", freq_file_name); + printf(" Result : %s\n", PRINT_RESULT(ERROR)); + fclose(fp); + return; + } + + freq /= 1000; + } else if (access(CPUINFO_FILE, F_OK) == 0) { + fp = fopen(CPUINFO_FILE, "r"); + if (!fp) { + printf("Failed to open %s\n", CPUINFO_FILE); + printf(" Result : %s\n", PRINT_RESULT(ERROR)); + return; + } + + freq = -1; + while (fgets(buf, BUF_SIZE, fp)) { + if (strncmp(buf, "cpu MHz", 7)) { + start = strchr(buf, ':') + 2; + sscanf(start, "%d", &freq); + break; + } + } + + if (freq == -1) { + printf("There is no information about cpu MHz in the %s\n", CPUINFO_FILE); + printf(" Result : %s\n", PRINT_RESULT(ERROR)); + fclose(fp); + return; + } + } else { + printf("There is no file providing CPU frequency\n"); + printf(" Result : %s\n", PRINT_RESULT(NOT_SUPPORTED)); + return; + } + + fclose(fp); + + printf(" %s CPU frequency of core 0 : %s\n", + (type == CUR) ? "Current" : "Max", + PRINT_RESULT(check_value(cpu_freq, freq, 0))); +} + +void runtime_info_test_get_processor_current_frequency(void) +{ + runtime_info_test_helper_get_processor_frequency( + "runtime_info_get_processor_current_frequency", CUR_FREQ_FILE, CUR); +} + +void runtime_info_test_get_processor_max_frequency(void) +{ + runtime_info_test_helper_get_processor_frequency( + "runtime_info_get_processor_max_frequency", MAX_FREQ_FILE, MAX); +} diff --git a/test/runtime_info_test_proc.c b/test/runtime_info_test_proc.c new file mode 100644 index 0000000..f7e24cb --- /dev/null +++ b/test/runtime_info_test_proc.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2011 - 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include + +#include "runtime_info_test.h" + +#define KiBtoPage(kib) (int)((kib) / 4.0) + +void runtime_info_test_get_system_memory_info(void) +{ + int ret; + runtime_memory_info_s info; + char buf[BUF_SIZE]; + FILE *fp; + unsigned long mem_total, mem_used, mem_free, cached, swap; + unsigned long mem_available, swap_total, swap_free; + + printf("Runtime_info_get_system_memory_info test\n"); + + ret = runtime_info_get_system_memory_info(&info); + if (ret) { + printf("runtime_info_get_system_memory_info failed (%d)\n", ret); + printf(" Result : %s\n", PRINT_RESULT(ERROR)); + return; + } + + fp = fopen("/proc/meminfo", "r"); + if (!fp) { + printf("Failed to read /proc/meminfo\n"); + printf(" Result : %s\n", PRINT_RESULT(ERROR)); + return; + } + + mem_total = mem_free = cached = mem_available = swap_total = swap_free = 0; + while (fgets(buf, BUF_SIZE, fp)) { + if (sscanf(buf, "MemTotal: %lu", &mem_total) == 1) + continue; + if (sscanf(buf, "MemFree: %lu", &mem_free) == 1) + continue; + if (sscanf(buf, "Cached: %lu", &cached) == 1) + continue; + if (sscanf(buf, "MemAvailable: %lu", &mem_available) == 1) + continue; + if (sscanf(buf, "SwapTotal: %lu", &swap_total) == 1) + continue; + if (sscanf(buf, "SwapFree: %lu", &swap_free) == 1) + continue; + } + + fclose(fp); + + if (mem_available > 0) { + if (mem_total > mem_available) + mem_used = mem_total - mem_available; + else + mem_used = 0; + } else { + if (mem_total > mem_free && mem_total - mem_free > cached) + mem_used = mem_total - mem_free - cached; + else + mem_used = 0; + } + + swap = (swap_total > swap_free) ? swap_total - swap_free : 0; + + printf(" Total memory size : %s\n", + PRINT_RESULT(check_value(info.total, mem_total, 0))); + printf(" Used memory size : %s\n", + PRINT_RESULT(check_value(info.used, mem_used, 0))); + printf(" Free memory size : %s\n", + PRINT_RESULT(check_value(info.free, mem_free, 0))); + printf(" Cache memory size : %s\n", + PRINT_RESULT(check_value(info.cache, cached, 0))); + printf(" Swap memory size : %s\n", + PRINT_RESULT(check_value(info.swap, swap, 0))); +} + +void runtime_info_test_get_cpu_usage(void) +{ + int ret; + runtime_cpu_usage_s usage; + char buf[BUF_SIZE]; + FILE *fp; + int total = 0; + unsigned long long user, nice, systime, idle, iowait, irq, softirq; + + printf("Runtime_info_get_cpu_usage test\n"); + + ret = runtime_info_get_cpu_usage(&usage); + if (ret) { + printf("runtime_info_get_cpu_usage failed (%d)\n", ret); + printf(" Result : %s\n", PRINT_RESULT(ERROR)); + return; + } + + fp = fopen("/proc/stat", "r"); + if (!fp) { + printf("Failed to read /proc/stat\n"); + printf(" Result : %s\n", PRINT_RESULT(ERROR)); + return; + } + + while (fgets(buf, BUF_SIZE, fp)) { + if (sscanf(buf, "cpu %llu %llu %llu %llu %llu %llu %llu", + &user, &nice, &systime, &idle, + &iowait, &irq, &softirq) == 7) + break; + } + + fclose(fp); + + total = user + nice + systime + idle + iowait + irq + softirq; + + user = (double)user * 100 / total; + nice = (double)nice * 100 / total; + systime = (double)systime * 100 / total; + iowait = (double)iowait * 100 / total; + + printf(" User time : %s\n", + PRINT_RESULT(check_value(usage.user, user, 1))); + printf(" Niced user time : %s\n", + PRINT_RESULT(check_value(usage.nice, nice, 1))); + printf(" System time : %s\n", + PRINT_RESULT(check_value(usage.system, systime, 1))); + printf(" IO wait time : %s\n", + PRINT_RESULT(check_value(usage.iowait, iowait, 1))); +} + +void runtime_info_test_get_physical_memory_size(void) +{ + int ret; + int size; + char buf[BUF_SIZE]; + FILE *fp; + unsigned long total, value; + + printf("Runtime_info_get_physical_memory_size test\n"); + + ret = runtime_info_get_physical_memory_size(&size); + if (ret) { + printf("runtime_info_get_physical_memory_size failed (%d)\n\n", ret); + printf(" Result : %s\n", PRINT_RESULT(ERROR)); + return; + } + + fp = fopen("/proc/zoneinfo", "r"); + if (!fp) { + printf("Failed to read /proc/zoneinfo\n"); + printf(" Result : %s\n", PRINT_RESULT(ERROR)); + return; + } + + total = 0; + while (fgets(buf, BUF_SIZE, fp)) + if (sscanf(buf, " spanned %lu", &value) == 1) + total += value; + + fclose(fp); + + printf(" Physical memory size : %s\n", + PRINT_RESULT(check_value(KiBtoPage(size), total, 0))); +} diff --git a/test/runtime_info_test_resourced.c b/test/runtime_info_test_resourced.c new file mode 100644 index 0000000..18b585c --- /dev/null +++ b/test/runtime_info_test_resourced.c @@ -0,0 +1,383 @@ +/* + * Copyright (c) 2011 - 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include + +#include "runtime_info_test.h" + +#define BytetoKiB(byte) (byte) >> 10 +#define KBtoPage(kb) ((kb) / 4) +#define START_TIME_FILE "/run/resourced/appinfo/%s/starttime" + +void runtime_info_test_get_process_memory_info(pid_t pid) +{ + int ret; + process_memory_info_s *info; + char buf[BUF_SIZE]; + FILE *fp; + unsigned long vsz; + int code, data, pss; + + printf("Runtime_info_get_process_memory_info test\n"); + + ret = runtime_info_get_process_memory_info(&pid, 1, &info); + if (ret) { + printf("runtime_info_get_process_memory_info failed (%d)\n\n", ret); + printf(" Result : %s\n", PRINT_RESULT(ERROR)); + return; + } + + /* Read /proc/PID/stat */ + snprintf(buf, BUF_SIZE, "/proc/%u/stat", pid); + fp = fopen(buf, "r"); + if (!fp) { + printf("Failed to open %s\n", buf); + printf(" Result : %s\n", PRINT_RESULT(ERROR)); + return; + } + + while (fgets(buf, BUF_SIZE, fp)) { + if (sscanf(buf, "%*d %*s %*c %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %lu", + &vsz) != 1) { + printf("/proc/%u/stat has invalid format\n", pid); + printf(" Result : %s\n", PRINT_RESULT(ERROR)); + fclose(fp); + return; + } + } + + fclose(fp); + + snprintf(buf, BUF_SIZE, "memps -a | grep runtime-info-test | grep %u", pid); + fp = popen(buf, "r"); + if (!fp) { + printf("popen failed\n"); + printf(" Result : %s\n", PRINT_RESULT(ERROR)); + return; + } + + if (!fscanf(fp, "%*d %d %d %*d %d", &code, &data, &pss)) { + printf("memps has invalid format\n"); + printf(" Result : %s\n", PRINT_RESULT(ERROR)); + fclose(fp); + return; + } + + fclose(fp); + + printf(" Virtual memory size : %s\n", + PRINT_RESULT(check_value(info[0].vsz, BytetoKiB(vsz), 0))); + printf(" Proportional set size : %s\n", + PRINT_RESULT(check_value(info[0].pss, pss, 0))); + printf(" Clean memory size : %s\n", + PRINT_RESULT(check_value(info[0].shared_clean + info[0].private_clean, + code, 0))); + printf(" Dirty memory size : %s\n", + PRINT_RESULT(check_value(info[0].shared_dirty + info[0].private_dirty, + data, 0))); +} + +void runtime_info_test_get_process_cpu_usage(pid_t pid) +{ + int ret; + process_cpu_usage_s *usage; + char buf[BUF_SIZE]; + FILE *fp; + unsigned long utime, stime; + + printf("Runtime_info_get_process_cpu_usage test\n"); + + ret = runtime_info_get_process_cpu_usage(&pid, 1, &usage); + if (ret) { + printf("runtime_info_get_process_cpu_usage failed (%d)\n\n", ret); + printf(" Result : %s\n", PRINT_RESULT(ERROR)); + return; + } + + snprintf(buf, BUF_SIZE, "/proc/%u/stat", pid); + fp = fopen(buf, "r"); + if (!fp) { + printf("Failed to open %s\n", buf); + printf(" Result : %s\n", PRINT_RESULT(ERROR)); + return; + } + + while (fgets(buf, BUF_SIZE, fp)) { + if (sscanf(buf, "%*d %*s %*c %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %lu %lu", + &utime, &stime) != 2) { + printf("/proc/%u/stat has invalid format\n", pid); + printf(" Result : %s\n", PRINT_RESULT(ERROR)); + fclose(fp); + return; + } + } + + fclose(fp); + + printf(" User time : %s\n", + PRINT_RESULT(check_value(usage[0].utime, utime, 0))); + printf(" System time : %s\n", + PRINT_RESULT(check_value(usage[0].stime, stime, 0))); +} + +static int runtime_info_test_helper_find_pid(app_usage_h *h, pid_t *pid) +{ + int ret; + int count; + char *appid = NULL; + char buf[BUF_SIZE]; + FILE *fp = NULL; + app_usage_h handle = *h; + int result = ERROR; + + ret = runtime_info_app_usage_get_count(handle, &count); + if (ret) { + printf("Failed to call runtime_info_app_usage_get_count (%d)\n\n", ret); + goto error; + } else if (count <= 0) { + printf("There is no launched app"); + goto error; + } + + ret = runtime_info_app_usage_get_appid(handle, 0, &appid); + if (ret) { + printf("Failed to call runtime_info_app_usage_get_appid (%d)\n\n", ret); + goto error; + } + + /* Find the pid of test app */ + snprintf(buf, BUF_SIZE, "/run/resourced/appinfo/%s/main_pid", appid); + fp = fopen(buf, "r"); + if (!fp) { + printf("Failed to open %s\n", buf); + goto error; + } + + if (!fscanf(fp, "%u", pid)) { + printf("There is no pid of %s in resourced appinfo\n", appid); + goto error; + } + + result = SUCCESS; + +error: + if (fp) + fclose(fp); + + if (appid) + free(appid); + + return result; +} + +void runtime_info_test_get_all_apps_memory_usage(void) +{ + int ret; + app_usage_h handle; + unsigned int usage_r; + long long usage; + char buf[BUF_SIZE]; + FILE *fp = NULL; + pid_t pid_app; + unsigned long resident, shared; + int vmswap; + + printf("Runtime_info_get_all_apps_memory_usage test\n"); + PRINT_NOTICE("Resourced-headless doesn't support this API.\n"); + + /* Call runtime-info APIs */ + ret = runtime_info_get_all_apps_memory_usage(&handle); + if (ret) { + printf("Failed to call runtime_info_get_all_apps_memory_usage (%d)\n\n", ret); + printf("Result : %s\n", PRINT_RESULT(ERROR)); + return; + } + + ret = runtime_info_app_usage_get_usage(handle, 0, &usage_r); + if (ret) { + printf("Failed to call runtime_info_app_usage_get_usage (%d)\n\n", ret); + goto error; + } + + if (runtime_info_test_helper_find_pid(&handle, &pid_app) == ERROR) + goto error; + + /* Read /proc/PID/statm */ + snprintf(buf, BUF_SIZE, "/proc/%u/statm", pid_app); + fp = fopen(buf, "r"); + if (!fp) { + printf("Failed to open %s\n", buf); + goto error; + } + + resident = shared = 0; + while (fgets(buf, BUF_SIZE, fp)) { + if (sscanf(buf, "%*s %lu %lu", &resident, &shared) != 2) { + printf("/proc/%u/statm has invalid format\n", pid_app); + fclose(fp); + goto error; + } + } + + fclose(fp); + + /* Read /proc/PID/status */ + snprintf(buf, BUF_SIZE, "/proc/%u/status", pid_app); + fp = fopen(buf, "r"); + if (!fp) { + printf("Failed to open %s\n", buf); + goto error; + } + + vmswap = 0; + while (fgets(buf, BUF_SIZE, fp)) { + if (sscanf(buf, "VmSwap: %d kB", &vmswap) == 1) + break; + } + + if (resident < shared) + usage = 0; + else + usage = resident - shared + KBtoPage(vmswap); + + fclose(fp); + ret = runtime_info_app_usage_destroy(handle); + + printf(" App memory usage : %s\n", + PRINT_RESULT(check_value(KBtoPage(usage_r), usage, 0))); + return; + +error: + printf(" Result : %s\n", PRINT_RESULT(ERROR)); + + ret = runtime_info_app_usage_destroy(handle); +} + +void runtime_info_test_get_all_apps_cpu_rate(void) +{ + int ret; + app_usage_h handle; + unsigned int rate_r, rate; + char *appid = NULL; + char buf[BUF_SIZE]; + FILE *fp = NULL; + pid_t pid_app; + unsigned int starttime, uptime; + unsigned long utime, stime, cputime; + + printf("Runtime_info_get_all_apps_cpu_rate test\n"); + PRINT_NOTICE("Resourced-headless doesn't support this API.\n"); + + /* Call runtime-info APIs */ + ret = runtime_info_get_all_apps_cpu_rate(&handle); + if (ret) { + printf("Failed to call runtime_info_get_all_apps_memory_usage (%d)\n\n", ret); + printf("Result : %s\n", PRINT_RESULT(ERROR)); + return; + } + + ret = runtime_info_app_usage_get_usage(handle, 0, &rate_r); + if (ret) { + printf("Failed to call runtime_info_app_usage_get_usage (%d)\n\n", ret); + goto error; + } + + ret = runtime_info_app_usage_get_appid(handle, 0, &appid); + if (ret) { + printf("Failed to call runtime_info_app_usage_get_appid (%d)\n\n", ret); + goto error; + } + + if (runtime_info_test_helper_find_pid(&handle, &pid_app) == ERROR) + goto error; + + /* Read starttime file */ + snprintf(buf, BUF_SIZE, START_TIME_FILE, appid); + fp = fopen(buf, "r"); + if (!fp) { + printf("Failed to open %s\n", buf); + goto error; + } + + if (!fscanf(fp, "%u", &starttime)) { + printf("%s has invalid format\n", buf); + goto error; + } + + fclose(fp); + + /* Read /proc/uptime */ + fp = fopen("/proc/uptime", "r"); + if (!fp) { + printf("Failed to open %s\n", buf); + goto error; + } + + if (!fscanf(fp, "%u", &uptime)) { + printf("%s has invalid format\n", buf); + goto error; + } + + fclose(fp); + + /* Read /proc/PID/stat */ + snprintf(buf, BUF_SIZE, "/proc/%u/stat", pid_app); + fp = fopen(buf, "r"); + if (!fp) { + printf("Failed to open %s\n", buf); + goto error; + } + + while (fgets(buf, BUF_SIZE, fp)) { + if (sscanf(buf, "%*d %*s %*c %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %lu %lu", + &utime, &stime) != 2) { + printf("/proc/%u/stat has invalid format\n", pid_app); + goto error; + } + } + + if (uptime <= starttime) + rate = 0; + else { + cputime = (unsigned long)(((unsigned long long)utime + stime) % UINT_MAX); + rate = cputime / (uptime - starttime); + } + + fclose(fp); + free(appid); + ret = runtime_info_app_usage_destroy(handle); + + printf(" App CPU rate : %s\n", + PRINT_RESULT(check_value(rate_r, rate, 5))); + return; + +error: + printf(" Result : %s\n", PRINT_RESULT(ERROR)); + + if (appid) + free(appid); + + if (fp) + fclose(fp); + + ret = runtime_info_app_usage_destroy(handle); +} diff --git a/test/runtime_info_test_vconf.c b/test/runtime_info_test_vconf.c new file mode 100644 index 0000000..e5ba13a --- /dev/null +++ b/test/runtime_info_test_vconf.c @@ -0,0 +1,355 @@ +/* + * Copyright (c) 2011 - 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "runtime_info_test.h" + +#define LIST_SIZE 5 +#define VCONF_KEY_OTHERS -1234 +#define KEY_GROUP_END -5678 + +#define MAX_TRIAL 5 +#define TIME_TO_WAIT_CB (2 * 1000000) /* 2 seconds */ + +static GCond cond; +static GMutex mutex; + +/* key_list_bool[CB_TEST_IDX] */ +#define CB_TEST_IDX 9 + +/** + * Lists are differently used depending on the tested type + * + * | bool | int + *---------------------------------------------------------------------- + * list1 | Values considered as True | Available vconf value list + * list2 | Values considered as False | Corresponded runtime-info value + */ +struct key_list { + char *name; + int key_r; + char *key_v; + int list1[LIST_SIZE]; + int list2[LIST_SIZE]; +}; + +static struct key_list key_list_bool[] = { + { + "Bluetooth", + RUNTIME_INFO_KEY_BLUETOOTH_ENABLED, + VCONFKEY_BT_STATUS, + { VCONFKEY_BT_STATUS_ON, VCONFKEY_BT_STATUS_BT_VISIBLE, VCONFKEY_BT_STATUS_TRANSFER, KEY_GROUP_END }, + { VCONFKEY_BT_STATUS_OFF, KEY_GROUP_END }, + }, + { + "Packet data", + RUNTIME_INFO_KEY_PACKET_DATA_ENABLED, + VCONFKEY_3G_ENABLE, + { KEY_GROUP_END }, + { KEY_GROUP_END }, + }, + { + "Data roaming", + RUNTIME_INFO_KEY_DATA_ROAMING_ENABLED, + VCONFKEY_SETAPPL_STATE_DATA_ROAMING_BOOL, + { KEY_GROUP_END }, + { KEY_GROUP_END }, + }, + { + "Vibration", + RUNTIME_INFO_KEY_VIBRATION_ENABLED, + VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL, + { KEY_GROUP_END }, + { KEY_GROUP_END }, + }, + { + "Audio jack connected", + RUNTIME_INFO_KEY_AUDIO_JACK_CONNECTED, + VCONFKEY_SYSMAN_EARJACK, + { VCONFKEY_SYSMAN_EARJACK_3WIRE, VCONFKEY_SYSMAN_EARJACK_4WIRE, KEY_GROUP_END }, + { VCONF_KEY_OTHERS, KEY_GROUP_END }, + }, + { + "Battery charging", + RUNTIME_INFO_KEY_BATTERY_IS_CHARGING, + VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW, + { VCONF_KEY_OTHERS, KEY_GROUP_END }, + { 0, KEY_GROUP_END }, + }, + { + "TV out", + RUNTIME_INFO_KEY_TV_OUT_CONNECTED, + VCONFKEY_SYSMAN_EARJACK, + { VCONFKEY_SYSMAN_EARJACK_TVOUT, KEY_GROUP_END }, + { VCONF_KEY_OTHERS, KEY_GROUP_END }, + }, + { + "USB connection", + RUNTIME_INFO_KEY_USB_CONNECTED, + VCONFKEY_SYSMAN_USB_STATUS, + { VCONFKEY_SYSMAN_USB_AVAILABLE, KEY_GROUP_END }, + { VCONFKEY_SYSMAN_USB_DISCONNECTED, VCONFKEY_SYSMAN_USB_CONNECTED, KEY_GROUP_END }, + }, + { + "Charger connection", + RUNTIME_INFO_KEY_CHARGER_CONNECTED, + VCONFKEY_SYSMAN_CHARGER_STATUS, + { VCONFKEY_SYSMAN_CHARGER_CONNECTED, KEY_GROUP_END }, + { VCONFKEY_SYSMAN_CHARGER_DISCONNECTED, KEY_GROUP_END }, + }, + { + "Auto rotation", + RUNTIME_INFO_KEY_AUTO_ROTATION_ENABLED, + VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, + { KEY_GROUP_END }, + { KEY_GROUP_END }, + }, +}; + +static struct key_list key_list_int[] = { + { + "GPS status", + RUNTIME_INFO_KEY_GPS_STATUS, + VCONFKEY_LOCATION_GPS_STATE, + { VCONFKEY_LOCATION_GPS_OFF, VCONFKEY_LOCATION_GPS_SEARCHING, VCONFKEY_LOCATION_GPS_CONNECTED, KEY_GROUP_END }, + { RUNTIME_INFO_GPS_STATUS_DISABLED, RUNTIME_INFO_GPS_STATUS_SEARCHING, RUNTIME_INFO_GPS_STATUS_CONNECTED, KEY_GROUP_END }, + }, + { + "Audiojack status", + RUNTIME_INFO_KEY_AUDIO_JACK_STATUS, + VCONFKEY_SYSMAN_EARJACK, + { VCONFKEY_SYSMAN_EARJACK_3WIRE, VCONFKEY_SYSMAN_EARJACK_4WIRE, VCONF_KEY_OTHERS, KEY_GROUP_END }, + { RUNTIME_INFO_AUDIO_JACK_STATUS_CONNECTED_3WIRE, RUNTIME_INFO_AUDIO_JACK_STATUS_CONNECTED_4WIRE, RUNTIME_INFO_AUDIO_JACK_STATUS_UNCONNECTED, KEY_GROUP_END }, + }, +}; + +void runtime_info_test_get_value_bool(void) +{ + int i, j; + int size = sizeof(key_list_bool) / sizeof(struct key_list); + int ret; + bool value_r; + int value_v; + int result; + + printf("Runtime_info_get_value_bool test\n"); + + for (i = 0; i < size; i++) { + result = SUCCESS; + + ret = runtime_info_get_value_bool(key_list_bool[i].key_r, &value_r); + switch (ret) { + case RUNTIME_INFO_ERROR_NONE: + if (key_list_bool[i].list1[0] == KEY_GROUP_END) { + ret = vconf_get_bool(key_list_bool[i].key_v, &value_v); + if (ret < 0) { + printf("vconf_get_bool error (%d)\n", ret); + result = ERROR; + break; + } + } else { + ret = vconf_get_int(key_list_bool[i].key_v, &value_v); + if (ret < 0) { + printf("vconf_get_int error (%d)\n", ret); + result = ERROR; + break; + } + + if (key_list_bool[i].list2[0] == VCONF_KEY_OTHERS) { + for (j = 0; j < LIST_SIZE; j++) { + if (key_list_bool[i].list1[j] == KEY_GROUP_END) { + value_v = false; + break; + } + if (key_list_bool[i].list1[j] == value_v) { + value_v = true; + break; + } + } + } else { + for (j = 0; j < LIST_SIZE; j++) { + if (key_list_bool[i].list2[j] == KEY_GROUP_END) { + value_v = true; + break; + } + if (key_list_bool[i].list2[j] == value_v) { + value_v = false; + break; + } + } + } + } + if (value_r != value_v) + result = FAIL; + break; + case RUNTIME_INFO_ERROR_NOT_SUPPORTED: + result = NOT_SUPPORTED; + break; + default: + printf("runtime_info_get_value_bool error (%d)\n", ret); + result = ERROR; + break; + } + + printf(" %s : %s\n", key_list_bool[i].name, PRINT_RESULT(result)); + } +} + +void runtime_info_test_get_value_int(void) +{ + int i, j; + int size = sizeof(key_list_int) / sizeof(struct key_list); + int ret; + int value_r, value_v; + int result; + + printf("Runtime_info_get_value_int test\n"); + + for (i = 0; i < size; i++) { + result = SUCCESS; + + ret = runtime_info_get_value_int(key_list_int[i].key_r, &value_r); + switch (ret) { + case RUNTIME_INFO_ERROR_NONE: + ret = vconf_get_int(key_list_int[i].key_v, &value_v); + if (ret < 0) { + printf("vconf_get_int error (%d)\n", ret); + result = ERROR; + break; + } + + for (j = 0; j < LIST_SIZE; j++) { + if (key_list_int[i].list1[j] == VCONF_KEY_OTHERS || + key_list_int[i].list1[j] == value_v) + value_v = key_list_int[i].list2[j]; + } + + if (value_r != value_v) + result = FAIL; + break; + case RUNTIME_INFO_ERROR_NOT_SUPPORTED: + result = NOT_SUPPORTED; + break; + default: + printf("runtime_info_get_value_int error (%d)\n", ret); + result = ERROR; + break; + } + + printf(" %s : %s\n", key_list_int[i].name, PRINT_RESULT(result)); + } +} + +static void runtime_info_test_changed_cb(runtime_info_key_e key, void *user_data) +{ + g_cond_signal(&cond); +} + +static gpointer runtime_info_test_cb_thread(gpointer data) +{ + int ret; + GMainLoop *mainloop = g_main_loop_new(NULL, FALSE); + if (!mainloop) + return NULL; + + ret = runtime_info_set_changed_cb(key_list_bool[CB_TEST_IDX].key_r, + runtime_info_test_changed_cb, key_list_bool[CB_TEST_IDX].name); + if (ret) { + printf("Failed to register callback. (%d)\n", ret); + return NULL; + } + + g_main_loop_run(mainloop); + + return NULL; +} + +void runtime_info_test_set_changed_cb(void) +{ + int ret; + bool value = false, value_orig = false; + char buf_t[BUF_SIZE]; + char buf_f[BUF_SIZE]; + int result = ERROR; + int trial = MAX_TRIAL; + + printf("Runtime_info_set_changed_cb test\n"); + + GThread *thread = g_thread_try_new(NULL, runtime_info_test_cb_thread, NULL, NULL); + if (!thread) { + printf("Failed to make callback thread\n"); + goto judge; + } + + ret = runtime_info_get_value_bool(key_list_bool[CB_TEST_IDX].key_r, &value_orig); + if (ret) { + printf("runtime_info_get_value_bool failed (%d)\n", ret); + goto judge; + } + value = value_orig; + + g_cond_init(&cond); + g_mutex_init(&mutex); + g_mutex_lock(&mutex); + + snprintf(buf_t, BUF_SIZE, "vconftool set -t bool %s -f 1", + key_list_bool[CB_TEST_IDX].key_v); + snprintf(buf_f, BUF_SIZE, "vconftool set -t bool %s -f 0", + key_list_bool[CB_TEST_IDX].key_v); + + for (; trial > 0; trial--) { + if (value) + ret = system(buf_f); + else + ret = system(buf_t); + if (ret == -1) { + printf("vconftool failed.\n"); + goto judge; + } + value = value ? false : true; + + if (g_cond_wait_until(&cond, &mutex, g_get_monotonic_time() + TIME_TO_WAIT_CB)) { + result = SUCCESS; + ret = runtime_info_unset_changed_cb(key_list_bool[CB_TEST_IDX].key_r); + break; + } + } + + if (trial == 0) { + printf("Callback isn't be called.\n"); + result = FAIL; + } + +judge: + printf(" Registering and calling callback : %s\n", PRINT_RESULT(result)); + + if (value != value_orig) { + if (value_orig) + ret = system(buf_t); + else + ret = system(buf_f); + } + + g_mutex_unlock(&mutex); +}