1// Copyright 2014 The Android Open Source Project
2//
3// This software is licensed under the terms of the GNU General Public
4// License version 2, as published by the Free Software Foundation, and
5// may be copied, distributed, and modified under those terms.
6//
7// This program is distributed in the hope that it will be useful,
8// but WITHOUT ANY WARRANTY; without even the implied warranty of
9// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10// GNU General Public License for more details.
11
12#include "android/utils/property_file.h"
13
14#include <stdlib.h>
15
16#include <gtest/gtest.h>
17
18// Unlike std::string, accept NULL as input.
19class String {
20public:
21    explicit String(const char* str) : mStr(str) {}
22    ~String() { free(const_cast<char*>(mStr)); }
23    const char* str() const { return mStr; }
24private:
25    const char* mStr;
26};
27
28TEST(PropertyFile, EmptyFile) {
29    EXPECT_FALSE(propertyFile_getValue("", 0U, "sdk.version"));
30}
31
32TEST(PropertyFile, SingleLineFile) {
33    static const char kFile[] = "foo=bar\n";
34    String value(propertyFile_getValue(kFile, sizeof kFile, "foo"));
35    EXPECT_TRUE(value.str());
36    EXPECT_STREQ("bar", value.str());
37
38    String value2(propertyFile_getValue(kFile, sizeof kFile, "bar"));
39    EXPECT_FALSE(value2.str());
40}
41
42TEST(PropertyFile, SingleLineFileWithZeroTerminator) {
43    static const char kFile[] = "foo=bar";
44    String value(propertyFile_getValue(kFile, sizeof kFile, "foo"));
45    EXPECT_TRUE(value.str());
46    EXPECT_STREQ("bar", value.str());
47
48    String value2(propertyFile_getValue(kFile, sizeof kFile, "bar"));
49    EXPECT_FALSE(value2.str());
50}
51
52TEST(PropertyFile, MultiLineFile) {
53    static const char kFile[] =
54        "foo=bar\n"
55        "bar=zoo\n"
56        "sdk=4.2\n";
57
58    String foo(propertyFile_getValue(kFile, sizeof kFile, "foo"));
59    String bar(propertyFile_getValue(kFile, sizeof kFile, "bar"));
60    String sdk(propertyFile_getValue(kFile, sizeof kFile, "sdk"));
61
62    EXPECT_STREQ("bar", foo.str());
63    EXPECT_STREQ("zoo", bar.str());
64    EXPECT_STREQ("4.2", sdk.str());
65}
66
67TEST(PropertyFile, MultiLineFileWithZeroTerminator) {
68    static const char kFile[] =
69        "foo=bar\n"
70        "bar=zoo\n"
71        "sdk=4.2";
72
73    String foo(propertyFile_getValue(kFile, sizeof kFile, "foo"));
74    String bar(propertyFile_getValue(kFile, sizeof kFile, "bar"));
75    String sdk(propertyFile_getValue(kFile, sizeof kFile, "sdk"));
76
77    EXPECT_STREQ("bar", foo.str());
78    EXPECT_STREQ("zoo", bar.str());
79    EXPECT_STREQ("4.2", sdk.str());
80}
81
82TEST(PropertyFile, MultiLineFileWithCRLF) {
83    static const char kFile[] =
84        "foo=bar\r\n"
85        "bar=zoo\r\n"
86        "sdk=4.2\n";
87
88    String foo(propertyFile_getValue(kFile, sizeof kFile, "foo"));
89    String bar(propertyFile_getValue(kFile, sizeof kFile, "bar"));
90    String sdk(propertyFile_getValue(kFile, sizeof kFile, "sdk"));
91
92    EXPECT_STREQ("bar", foo.str());
93    EXPECT_STREQ("zoo", bar.str());
94    EXPECT_STREQ("4.2", sdk.str());
95}
96
97TEST(PropertyFile, SpaceAroundPropertyNameAndValues) {
98    static const char kFile[] = "  foo = bar zoo \n";
99    String foo(propertyFile_getValue(kFile, sizeof kFile, "foo"));
100    EXPECT_STREQ(" bar zoo ", foo.str());
101}
102
103TEST(PropertyFile, ValueTooLongIsTruncated) {
104    static const char kFile[] =
105        "foo=This is an incredible long value that is going to be truncated"
106        " by the property file parser since it is longer than "
107        "MAX_PROPERTY_VALUE_LEN\n";
108    char expected[MAX_PROPERTY_VALUE_LEN];
109    memcpy(expected, kFile + 4, sizeof expected);
110    expected[(sizeof expected) - 1U] = 0;
111
112    String foo(propertyFile_getValue(kFile, sizeof kFile, "foo"));
113    EXPECT_STREQ(expected, foo.str());
114}
115
116TEST(PropertyFile, ReturnLatestVariableDefinition) {
117    static const char kFile[] = "foo=bar\nfoo=zoo\n";
118    String foo(propertyFile_getValue(kFile, sizeof kFile, "foo"));
119    EXPECT_STREQ("zoo", foo.str());
120}
121
122TEST(PropertyFile, Iterator) {
123    static const char kFile[] =
124            "foo=bar\n"
125            "this-name-is-too-long-and-will-be-ignored-by-the-parser=ahah\n"
126            "foo2=this-value-is-too-long-and-will-be-truncated-by-the-parser"
127                    "-which-only-wants-something-smaller-than-92-bytes\n"
128            "foo3=bar\r\n"
129            "bar= zoo";
130
131    PropertyFileIterator iter[1];
132    propertyFileIterator_init(iter, kFile, sizeof kFile);
133
134    EXPECT_TRUE(propertyFileIterator_next(iter));
135    EXPECT_STREQ("foo", iter->name);
136    EXPECT_STREQ("bar", iter->value);
137
138    EXPECT_TRUE(propertyFileIterator_next(iter));
139    EXPECT_STREQ("foo2", iter->name);
140    EXPECT_STREQ("this-value-is-too-long-and-will-be-truncated-by-the-"
141                 "parser-which-only-wants-something-small", iter->value);
142
143    EXPECT_TRUE(propertyFileIterator_next(iter));
144    EXPECT_STREQ("foo3", iter->name);
145    EXPECT_STREQ("bar", iter->value);
146
147    EXPECT_TRUE(propertyFileIterator_next(iter));
148    EXPECT_STREQ("bar", iter->name);
149    EXPECT_STREQ(" zoo", iter->value);
150
151    EXPECT_FALSE(propertyFileIterator_next(iter));
152}
153