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 #if defined(__SSE4_2__)
28 #  define RAPIDJSON_SSE42
29 #elif defined(__SSE2__)
30 #  define RAPIDJSON_SSE2
31 #endif
32 
33 #define RAPIDJSON_HAS_STDSTRING 1
34 
35 ////////////////////////////////////////////////////////////////////////////////
36 // Google Test
37 
38 #ifdef __cplusplus
39 
40 // gtest indirectly included inttypes.h, without __STDC_CONSTANT_MACROS.
41 #ifndef __STDC_CONSTANT_MACROS
42 #  define __STDC_CONSTANT_MACROS 1 // required by C++ standard
43 #endif
44 
45 #if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))
46 #if defined(__clang__) || (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
47 #pragma GCC diagnostic push
48 #endif
49 #pragma GCC diagnostic ignored "-Weffc++"
50 #endif
51 
52 #include "gtest/gtest.h"
53 
54 #if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
55 #pragma GCC diagnostic pop
56 #endif
57 
58 #ifdef _MSC_VER
59 #define _CRTDBG_MAP_ALLOC
60 #include <crtdbg.h>
61 #pragma warning(disable : 4996) // 'function': was declared deprecated
62 #endif
63 
64 //! Base class for all performance tests
65 class PerfTest : public ::testing::Test {
66 public:
PerfTest()67     PerfTest() : filename_(), json_(), length_(), whitespace_(), whitespace_length_() {}
68 
SetUp()69     virtual void SetUp() {
70         {
71             const char *paths[] = {
72                 "data/sample.json",
73                 "bin/data/sample.json",
74                 "../bin/data/sample.json",
75                 "../../bin/data/sample.json",
76                 "../../../bin/data/sample.json"
77             };
78 
79             FILE *fp = 0;
80             for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) {
81                 fp = fopen(filename_ = paths[i], "rb");
82                 if (fp)
83                     break;
84             }
85             ASSERT_TRUE(fp != 0);
86 
87             fseek(fp, 0, SEEK_END);
88             length_ = (size_t)ftell(fp);
89             fseek(fp, 0, SEEK_SET);
90             json_ = (char*)malloc(length_ + 1);
91             ASSERT_EQ(length_, fread(json_, 1, length_, fp));
92             json_[length_] = '\0';
93             fclose(fp);
94         }
95 
96         // whitespace test
97         {
98             whitespace_length_ = 1024 * 1024;
99             whitespace_ = (char *)malloc(whitespace_length_  + 4);
100             char *p = whitespace_;
101             for (size_t i = 0; i < whitespace_length_; i += 4) {
102                 *p++ = ' ';
103                 *p++ = '\n';
104                 *p++ = '\r';
105                 *p++ = '\t';
106             }
107             *p++ = '[';
108             *p++ = '0';
109             *p++ = ']';
110             *p++ = '\0';
111         }
112 
113         // types test
114         {
115             const char *typespaths[] = {
116                 "data/types",
117                 "bin/types",
118                 "../bin/types",
119                 "../../bin/types/",
120                 "../../../bin/types"
121             };
122 
123             const char* typesfilenames[] = {
124                 "booleans.json",
125                 "floats.json",
126                 "guids.json",
127                 "integers.json",
128                 "mixed.json",
129                 "nulls.json",
130                 "paragraphs.json"
131             };
132 
133             for (size_t j = 0; j < sizeof(typesfilenames) / sizeof(typesfilenames[0]); j++) {
134                 types_[j] = 0;
135                 for (size_t i = 0; i < sizeof(typespaths) / sizeof(typespaths[0]); i++) {
136                     char filename[256];
137                     sprintf(filename, "%s/%s", typespaths[i], typesfilenames[j]);
138                     if (FILE* fp = fopen(filename, "rb")) {
139                         fseek(fp, 0, SEEK_END);
140                         typesLength_[j] = (size_t)ftell(fp);
141                         fseek(fp, 0, SEEK_SET);
142                         types_[j] = (char*)malloc(typesLength_[j] + 1);
143                         ASSERT_EQ(typesLength_[j], fread(types_[j], 1, typesLength_[j], fp));
144                         types_[j][typesLength_[j]] = '\0';
145                         fclose(fp);
146                         break;
147                     }
148                 }
149             }
150         }
151     }
152 
TearDown()153     virtual void TearDown() {
154         free(json_);
155         free(whitespace_);
156         json_ = 0;
157         whitespace_ = 0;
158         for (size_t i = 0; i < 7; i++) {
159             free(types_[i]);
160             types_[i] = 0;
161         }
162     }
163 
164 private:
165     PerfTest(const PerfTest&);
166     PerfTest& operator=(const PerfTest&);
167 
168 protected:
169     const char* filename_;
170     char *json_;
171     size_t length_;
172     char *whitespace_;
173     size_t whitespace_length_;
174     char *types_[7];
175     size_t typesLength_[7];
176 
177     static const size_t kTrialCount = 1000;
178 };
179 
180 #endif // __cplusplus
181 
182 #endif // PERFTEST_H_
183