1 // Tencent is pleased to support the open source community by making RapidJSON available.
2 //
3 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
4 //
5 // Licensed under the MIT License (the "License"); you may not use this file except
6 // in compliance with the License. You may obtain a copy of the License at
7 //
8 // http://opensource.org/licenses/MIT
9 //
10 // Unless required by applicable law or agreed to in writing, software distributed
11 // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 // specific language governing permissions and limitations under the License.
14 
15 #ifndef PERFTEST_H_
16 #define PERFTEST_H_
17 
18 #define TEST_RAPIDJSON  1
19 #define TEST_PLATFORM   0
20 #define TEST_MISC       0
21 
22 #define TEST_VERSION_CODE(x,y,z) \
23   (((x)*100000) + ((y)*100) + (z))
24 
25 // __SSE2__ and __SSE4_2__ are recognized by gcc, clang, and the Intel compiler.
26 // We use -march=native with gmake to enable -msse2 and -msse4.2, if supported.
27 // Likewise, __ARM_NEON is used to detect Neon.
28 #if defined(__SSE4_2__)
29 #  define RAPIDJSON_SSE42
30 #elif defined(__SSE2__)
31 #  define RAPIDJSON_SSE2
32 #elif defined(__ARM_NEON)
33 #  define RAPIDJSON_NEON
34 #endif
35 
36 #define RAPIDJSON_HAS_STDSTRING 1
37 
38 ////////////////////////////////////////////////////////////////////////////////
39 // Google Test
40 
41 #ifdef __cplusplus
42 
43 // gtest indirectly included inttypes.h, without __STDC_CONSTANT_MACROS.
44 #ifndef __STDC_CONSTANT_MACROS
45 #  define __STDC_CONSTANT_MACROS 1 // required by C++ standard
46 #endif
47 
48 #if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))
49 #if defined(__clang__) || (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
50 #pragma GCC diagnostic push
51 #endif
52 #pragma GCC diagnostic ignored "-Weffc++"
53 #endif
54 
55 #include "gtest/gtest.h"
56 
57 #if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
58 #pragma GCC diagnostic pop
59 #endif
60 
61 #ifdef _MSC_VER
62 #define _CRTDBG_MAP_ALLOC
63 #include <crtdbg.h>
64 #pragma warning(disable : 4996) // 'function': was declared deprecated
65 #endif
66 
67 //! Base class for all performance tests
68 class PerfTest : public ::testing::Test {
69 public:
PerfTest()70     PerfTest() : filename_(), json_(), length_(), whitespace_(), whitespace_length_() {}
71 
SetUp()72     virtual void SetUp() {
73         {
74             const char *paths[] = {
75                 "data/sample.json",
76                 "bin/data/sample.json",
77                 "../bin/data/sample.json",
78                 "../../bin/data/sample.json",
79                 "../../../bin/data/sample.json"
80             };
81 
82             FILE *fp = 0;
83             for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) {
84                 fp = fopen(filename_ = paths[i], "rb");
85                 if (fp)
86                     break;
87             }
88             ASSERT_TRUE(fp != 0);
89 
90             fseek(fp, 0, SEEK_END);
91             length_ = (size_t)ftell(fp);
92             fseek(fp, 0, SEEK_SET);
93             json_ = (char*)malloc(length_ + 1);
94             ASSERT_EQ(length_, fread(json_, 1, length_, fp));
95             json_[length_] = '\0';
96             fclose(fp);
97         }
98 
99         // whitespace test
100         {
101             whitespace_length_ = 1024 * 1024;
102             whitespace_ = (char *)malloc(whitespace_length_  + 4);
103             char *p = whitespace_;
104             for (size_t i = 0; i < whitespace_length_; i += 4) {
105                 *p++ = ' ';
106                 *p++ = '\n';
107                 *p++ = '\r';
108                 *p++ = '\t';
109             }
110             *p++ = '[';
111             *p++ = '0';
112             *p++ = ']';
113             *p++ = '\0';
114         }
115 
116         // types test
117         {
118             const char *typespaths[] = {
119                 "data/types",
120                 "bin/types",
121                 "../bin/types",
122                 "../../bin/types/",
123                 "../../../bin/types"
124             };
125 
126             const char* typesfilenames[] = {
127                 "booleans.json",
128                 "floats.json",
129                 "guids.json",
130                 "integers.json",
131                 "mixed.json",
132                 "nulls.json",
133                 "paragraphs.json"
134             };
135 
136             for (size_t j = 0; j < sizeof(typesfilenames) / sizeof(typesfilenames[0]); j++) {
137                 types_[j] = 0;
138                 for (size_t i = 0; i < sizeof(typespaths) / sizeof(typespaths[0]); i++) {
139                     char filename[256];
140                     sprintf(filename, "%s/%s", typespaths[i], typesfilenames[j]);
141                     if (FILE* fp = fopen(filename, "rb")) {
142                         fseek(fp, 0, SEEK_END);
143                         typesLength_[j] = (size_t)ftell(fp);
144                         fseek(fp, 0, SEEK_SET);
145                         types_[j] = (char*)malloc(typesLength_[j] + 1);
146                         ASSERT_EQ(typesLength_[j], fread(types_[j], 1, typesLength_[j], fp));
147                         types_[j][typesLength_[j]] = '\0';
148                         fclose(fp);
149                         break;
150                     }
151                 }
152             }
153         }
154     }
155 
TearDown()156     virtual void TearDown() {
157         free(json_);
158         free(whitespace_);
159         json_ = 0;
160         whitespace_ = 0;
161         for (size_t i = 0; i < 7; i++) {
162             free(types_[i]);
163             types_[i] = 0;
164         }
165     }
166 
167 private:
168     PerfTest(const PerfTest&);
169     PerfTest& operator=(const PerfTest&);
170 
171 protected:
172     const char* filename_;
173     char *json_;
174     size_t length_;
175     char *whitespace_;
176     size_t whitespace_length_;
177     char *types_[7];
178     size_t typesLength_[7];
179 
180     static const size_t kTrialCount = 1000;
181 };
182 
183 #endif // __cplusplus
184 
185 #endif // PERFTEST_H_
186