1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <fcntl.h>
18#include <sys/cdefs.h>
19
20#include <gtest/gtest.h>
21
22// Should be in bionic test suite, *but* we are using liblog to confirm
23// end-to-end logging, so let the overly cute oedipus complex begin ...
24#include "../../../../bionic/libc/bionic/libc_logging.cpp" // not Standalone
25#define _ANDROID_LOG_H // Priorities redefined
26#define _LIBS_LOG_LOG_H // log ids redefined
27typedef unsigned char log_id_t; // log_id_t missing as a result
28#ifdef TARGET_USES_LOGD
29#define _LIBS_LOG_LOG_READ_H // log_time redefined
30#endif
31
32#include <log/log.h>
33#include <log/logger.h>
34#include <log/log_read.h>
35
36TEST(libc, __libc_android_log_event_int) {
37    struct logger_list *logger_list;
38
39    pid_t pid = getpid();
40
41    ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
42        LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
43
44    struct timespec ts;
45    clock_gettime(CLOCK_MONOTONIC, &ts);
46    int value = ts.tv_nsec;
47
48    __libc_android_log_event_int(0, value);
49    usleep(1000000);
50
51    int count = 0;
52
53    for (;;) {
54        log_msg log_msg;
55        if (android_logger_list_read(logger_list, &log_msg) <= 0) {
56            break;
57        }
58
59        ASSERT_EQ(log_msg.entry.pid, pid);
60
61        if ((log_msg.entry.len != (4 + 1 + 4))
62         || ((int)log_msg.id() != LOG_ID_EVENTS)) {
63            continue;
64        }
65
66        char *eventData = log_msg.msg();
67
68        int incoming = (eventData[0] & 0xFF) |
69                      ((eventData[1] & 0xFF) << 8) |
70                      ((eventData[2] & 0xFF) << 16) |
71                      ((eventData[3] & 0xFF) << 24);
72
73        if (incoming != 0) {
74            continue;
75        }
76
77        if (eventData[4] != EVENT_TYPE_INT) {
78            continue;
79        }
80
81        incoming = (eventData[4 + 1 + 0] & 0xFF) |
82                  ((eventData[4 + 1 + 1] & 0xFF) << 8) |
83                  ((eventData[4 + 1 + 2] & 0xFF) << 16) |
84                  ((eventData[4 + 1 + 3] & 0xFF) << 24);
85
86        if (incoming == value) {
87            ++count;
88        }
89    }
90
91    EXPECT_EQ(1, count);
92
93    android_logger_list_close(logger_list);
94}
95
96TEST(libc, __libc_fatal_no_abort) {
97    struct logger_list *logger_list;
98
99    pid_t pid = getpid();
100
101    ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
102        (log_id_t)LOG_ID_CRASH, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
103
104    char b[80];
105    struct timespec ts;
106    clock_gettime(CLOCK_MONOTONIC, &ts);
107
108    __libc_fatal_no_abort("%u.%09u", (unsigned)ts.tv_sec, (unsigned)ts.tv_nsec);
109    snprintf(b, sizeof(b),"%u.%09u", (unsigned)ts.tv_sec, (unsigned)ts.tv_nsec);
110    usleep(1000000);
111
112    int count = 0;
113
114    for (;;) {
115        log_msg log_msg;
116        if (android_logger_list_read(logger_list, &log_msg) <= 0) {
117            break;
118        }
119
120        ASSERT_EQ(log_msg.entry.pid, pid);
121
122        if ((int)log_msg.id() != LOG_ID_CRASH) {
123            continue;
124        }
125
126        char *data = log_msg.msg();
127
128        if ((*data == ANDROID_LOG_FATAL)
129                && !strcmp(data + 1, "libc")
130                && !strcmp(data + 1 + strlen(data + 1) + 1, b)) {
131            ++count;
132        }
133    }
134
135    EXPECT_EQ(1, count);
136
137    android_logger_list_close(logger_list);
138}
139
140TEST(libc, __pstore_append) {
141    FILE *fp;
142    ASSERT_TRUE(NULL != (fp = fopen("/dev/pmsg0", "a")));
143    static const char message[] = "libc.__pstore_append\n";
144    ASSERT_EQ((size_t)1, fwrite(message, sizeof(message), 1, fp));
145    ASSERT_EQ(0, fclose(fp));
146    fprintf(stderr, "Reboot, ensure string libc.__pstore_append is in /sys/fs/pstore/pmsg-ramoops-0\n");
147}
148