1// Copyright (c) 2013, Google Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8//     * Redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer.
10//     * Redistributions in binary form must reproduce the above
11// copyright notice, this list of conditions and the following disclaimer
12// in the documentation and/or other materials provided with the
13// distribution.
14//     * Neither the name of Google Inc. nor the names of its
15// contributors may be used to endorse or promote products derived from
16// this software without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30#include <stdlib.h>
31#include <unistd.h>
32#include <sys/types.h>
33#include <stdio.h>
34#include <errno.h>
35#include <string.h>
36
37#include "client/linux/minidump_writer/proc_cpuinfo_reader.h"
38#include "breakpad_googletest_includes.h"
39#include "common/linux/tests/auto_testfile.h"
40
41using namespace google_breakpad;
42
43#if !defined(__ANDROID__)
44#define TEMPDIR "/tmp"
45#else
46#define TEMPDIR "/data/local/tmp"
47#endif
48
49
50namespace {
51
52typedef testing::Test ProcCpuInfoReaderTest;
53
54class ScopedTestFile : public AutoTestFile {
55public:
56  explicit ScopedTestFile(const char* text)
57    : AutoTestFile("proc_cpuinfo_reader", text) {
58  }
59};
60
61}
62
63TEST(ProcCpuInfoReaderTest, EmptyFile) {
64  ScopedTestFile file("");
65  ASSERT_TRUE(file.IsOk());
66  ProcCpuInfoReader reader(file.GetFd());
67
68  const char *field;
69  ASSERT_FALSE(reader.GetNextField(&field));
70}
71
72TEST(ProcCpuInfoReaderTest, OneLineTerminated) {
73  ScopedTestFile file("foo : bar\n");
74  ASSERT_TRUE(file.IsOk());
75  ProcCpuInfoReader reader(file.GetFd());
76
77  const char *field;
78  ASSERT_TRUE(reader.GetNextField(&field));
79  ASSERT_STREQ("foo", field);
80  ASSERT_STREQ("bar", reader.GetValue());
81
82  ASSERT_FALSE(reader.GetNextField(&field));
83}
84
85TEST(ProcCpuInfoReaderTest, OneLine) {
86  ScopedTestFile file("foo : bar");
87  ASSERT_TRUE(file.IsOk());
88  ProcCpuInfoReader reader(file.GetFd());
89
90  const char *field;
91  size_t value_len;
92  ASSERT_TRUE(reader.GetNextField(&field));
93  ASSERT_STREQ("foo", field);
94  ASSERT_STREQ("bar", reader.GetValueAndLen(&value_len));
95  ASSERT_EQ(3U, value_len);
96
97  ASSERT_FALSE(reader.GetNextField(&field));
98}
99
100TEST(ProcCpuInfoReaderTest, TwoLinesTerminated) {
101  ScopedTestFile file("foo : bar\nzoo : tut\n");
102  ASSERT_TRUE(file.IsOk());
103  ProcCpuInfoReader reader(file.GetFd());
104
105  const char* field;
106  ASSERT_TRUE(reader.GetNextField(&field));
107  ASSERT_STREQ("foo", field);
108  ASSERT_STREQ("bar", reader.GetValue());
109
110  ASSERT_TRUE(reader.GetNextField(&field));
111  ASSERT_STREQ("zoo", field);
112  ASSERT_STREQ("tut", reader.GetValue());
113
114  ASSERT_FALSE(reader.GetNextField(&field));
115}
116
117TEST(ProcCpuInfoReaderTest, SkipMalformedLine) {
118  ScopedTestFile file("this line should have a column\nfoo : bar\n");
119  ASSERT_TRUE(file.IsOk());
120  ProcCpuInfoReader reader(file.GetFd());
121
122  const char* field;
123  ASSERT_TRUE(reader.GetNextField(&field));
124  ASSERT_STREQ("foo", field);
125  ASSERT_STREQ("bar", reader.GetValue());
126
127  ASSERT_FALSE(reader.GetNextField(&field));
128}
129
130TEST(ProcCpuInfoReaderTest, SkipOneEmptyLine) {
131  ScopedTestFile file("\n\nfoo : bar\n");
132  ASSERT_TRUE(file.IsOk());
133  ProcCpuInfoReader reader(file.GetFd());
134
135  const char* field;
136  ASSERT_TRUE(reader.GetNextField(&field));
137  ASSERT_STREQ("foo", field);
138  ASSERT_STREQ("bar", reader.GetValue());
139
140  ASSERT_FALSE(reader.GetNextField(&field));
141}
142
143TEST(ProcCpuInfoReaderTest, SkipEmptyField) {
144  ScopedTestFile file(" : bar\nzoo : tut\n");
145  ASSERT_TRUE(file.IsOk());
146  ProcCpuInfoReader reader(file.GetFd());
147
148  const char* field;
149  ASSERT_TRUE(reader.GetNextField(&field));
150  ASSERT_STREQ("zoo", field);
151  ASSERT_STREQ("tut", reader.GetValue());
152
153  ASSERT_FALSE(reader.GetNextField(&field));
154}
155
156TEST(ProcCpuInfoReaderTest, SkipTwoEmptyLines) {
157  ScopedTestFile file("foo : bar\n\n\nfoo : bar\n");
158  ASSERT_TRUE(file.IsOk());
159  ProcCpuInfoReader reader(file.GetFd());
160
161  const char* field;
162  ASSERT_TRUE(reader.GetNextField(&field));
163  ASSERT_STREQ("foo", field);
164  ASSERT_STREQ("bar", reader.GetValue());
165
166  ASSERT_TRUE(reader.GetNextField(&field));
167  ASSERT_STREQ("foo", field);
168  ASSERT_STREQ("bar", reader.GetValue());
169
170  ASSERT_FALSE(reader.GetNextField(&field));
171}
172
173TEST(ProcCpuInfoReaderTest, FieldWithSpaces) {
174  ScopedTestFile file("foo bar    : zoo\n");
175  ASSERT_TRUE(file.IsOk());
176  ProcCpuInfoReader reader(file.GetFd());
177
178  const char* field;
179  ASSERT_TRUE(reader.GetNextField(&field));
180  ASSERT_STREQ("foo bar", field);
181  ASSERT_STREQ("zoo", reader.GetValue());
182
183  ASSERT_FALSE(reader.GetNextField(&field));
184}
185
186TEST(ProcCpuInfoReaderTest, EmptyValue) {
187  ScopedTestFile file("foo :\n");
188  ASSERT_TRUE(file.IsOk());
189  ProcCpuInfoReader reader(file.GetFd());
190
191  const char* field;
192  ASSERT_TRUE(reader.GetNextField(&field));
193  ASSERT_STREQ("foo", field);
194  size_t value_len;
195  ASSERT_STREQ("", reader.GetValueAndLen(&value_len));
196  ASSERT_EQ(0U, value_len);
197
198  ASSERT_FALSE(reader.GetNextField(&field));
199}
200