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#define _LIBS_LOG_LOG_READ_H // log_time redefined
29
30#include <log/log.h>
31#include <log/logger.h>
32#include <log/log_read.h>
33
34TEST(libc, __libc_android_log_event_int) {
35    struct logger_list *logger_list;
36
37    pid_t pid = getpid();
38
39    ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
40        LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
41
42    struct timespec ts;
43    clock_gettime(CLOCK_MONOTONIC, &ts);
44    int value = ts.tv_nsec;
45
46    __libc_android_log_event_int(0, value);
47    usleep(1000000);
48
49    int count = 0;
50
51    for (;;) {
52        log_msg log_msg;
53        if (android_logger_list_read(logger_list, &log_msg) <= 0) {
54            break;
55        }
56
57        ASSERT_EQ(log_msg.entry.pid, pid);
58
59        if ((log_msg.entry.len != (4 + 1 + 4))
60         || ((int)log_msg.id() != LOG_ID_EVENTS)) {
61            continue;
62        }
63
64        char *eventData = log_msg.msg();
65
66        int incoming = (eventData[0] & 0xFF) |
67                      ((eventData[1] & 0xFF) << 8) |
68                      ((eventData[2] & 0xFF) << 16) |
69                      ((eventData[3] & 0xFF) << 24);
70
71        if (incoming != 0) {
72            continue;
73        }
74
75        if (eventData[4] != EVENT_TYPE_INT) {
76            continue;
77        }
78
79        incoming = (eventData[4 + 1 + 0] & 0xFF) |
80                  ((eventData[4 + 1 + 1] & 0xFF) << 8) |
81                  ((eventData[4 + 1 + 2] & 0xFF) << 16) |
82                  ((eventData[4 + 1 + 3] & 0xFF) << 24);
83
84        if (incoming == value) {
85            ++count;
86        }
87    }
88
89    EXPECT_EQ(1, count);
90
91    android_logger_list_close(logger_list);
92}
93
94TEST(libc, __libc_fatal_no_abort) {
95    struct logger_list *logger_list;
96
97    pid_t pid = getpid();
98
99    ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
100        (log_id_t)LOG_ID_CRASH, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
101
102    char b[80];
103    struct timespec ts;
104    clock_gettime(CLOCK_MONOTONIC, &ts);
105
106    __libc_fatal_no_abort("%u.%09u", (unsigned)ts.tv_sec, (unsigned)ts.tv_nsec);
107    snprintf(b, sizeof(b),"%u.%09u", (unsigned)ts.tv_sec, (unsigned)ts.tv_nsec);
108    usleep(1000000);
109
110    int count = 0;
111
112    for (;;) {
113        log_msg log_msg;
114        if (android_logger_list_read(logger_list, &log_msg) <= 0) {
115            break;
116        }
117
118        ASSERT_EQ(log_msg.entry.pid, pid);
119
120        if ((int)log_msg.id() != LOG_ID_CRASH) {
121            continue;
122        }
123
124        char *data = log_msg.msg();
125
126        if ((*data == ANDROID_LOG_FATAL)
127                && !strcmp(data + 1, "libc")
128                && !strcmp(data + 1 + strlen(data + 1) + 1, b)) {
129            ++count;
130        }
131    }
132
133    EXPECT_EQ(1, count);
134
135    android_logger_list_close(logger_list);
136}
137
138TEST(libc, __pstore_append) {
139    FILE *fp;
140    ASSERT_TRUE(NULL != (fp = fopen("/dev/pmsg0", "a")));
141    static const char message[] = "libc.__pstore_append\n";
142    ASSERT_EQ((size_t)1, fwrite(message, sizeof(message), 1, fp));
143    ASSERT_EQ(0, fclose(fp));
144    fprintf(stderr, "Reboot, ensure string libc.__pstore_append is in /sys/fs/pstore/pmsg-ramoops-0\n");
145}
146