Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(403)

Side by Side Diff: mojo/public/cpp/bindings/tests/validation_test_input_parser.cc

Issue 327323003: Support [handles] in validation test input format and add handle-related tests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "mojo/public/cpp/bindings/tests/validation_test_input_parser.h" 5 #include "mojo/public/cpp/bindings/tests/validation_test_input_parser.h"
6 6
7 #include <assert.h> 7 #include <assert.h>
8 #include <stdio.h> 8 #include <stdio.h>
9 #include <string.h> 9 #include <string.h>
10 10
11 #include <limits> 11 #include <limits>
12 #include <map> 12 #include <map>
13 #include <utility> 13 #include <utility>
14 14
15 #include "mojo/public/c/system/macros.h" 15 #include "mojo/public/c/system/macros.h"
16 16
17 namespace mojo { 17 namespace mojo {
18 namespace test { 18 namespace test {
19 namespace { 19 namespace {
20 20
21 class ValidationTestInputParser { 21 class ValidationTestInputParser {
22 public: 22 public:
23 ValidationTestInputParser(const std::string& input, 23 ValidationTestInputParser(const std::string& input,
24 std::vector<uint8_t>* parsed_input, 24 std::vector<uint8_t>* data,
25 size_t* num_handles,
25 std::string* error_message); 26 std::string* error_message);
26 ~ValidationTestInputParser(); 27 ~ValidationTestInputParser();
27 28
28 bool Run(); 29 bool Run();
29 30
30 private: 31 private:
31 struct DataType; 32 struct DataType;
32 33
33 typedef std::pair<const char*, const char*> Range; 34 typedef std::pair<const char*, const char*> Range;
34 35
35 typedef bool (ValidationTestInputParser::*ParseDataFunc)( 36 typedef bool (ValidationTestInputParser::*ParseDataFunc)(
36 const DataType& type, const std::string& value_string); 37 const DataType& type, const std::string& value_string);
37 38
38 struct DataType { 39 struct DataType {
39 const char* name; 40 const char* name;
40 size_t name_size; 41 size_t name_size;
41 size_t data_size; 42 size_t data_size;
42 ParseDataFunc parse_data_func; 43 ParseDataFunc parse_data_func;
43 }; 44 };
44 45
45 // A dist4/8 item that hasn't been matched with an anchr item. 46 // A dist4/8 item that hasn't been matched with an anchr item.
46 struct PendingDistanceItem { 47 struct PendingDistanceItem {
47 // Where this data item is located in |parsed_input_|. 48 // Where this data item is located in |data_|.
48 size_t pos; 49 size_t pos;
49 // Either 4 or 8 (bytes). 50 // Either 4 or 8 (bytes).
50 size_t data_size; 51 size_t data_size;
51 }; 52 };
52 53
53 bool GetNextItem(Range* range); 54 bool GetNextItem(Range* range);
54 55
55 bool ParseItem(const Range& range); 56 bool ParseItem(const Range& range);
56 57
57 bool ParseUnsignedInteger(const DataType& type, 58 bool ParseUnsignedInteger(const DataType& type,
58 const std::string& value_string); 59 const std::string& value_string);
59 bool ParseSignedInteger(const DataType& type, 60 bool ParseSignedInteger(const DataType& type,
60 const std::string& value_string); 61 const std::string& value_string);
61 bool ParseFloat(const DataType& type, const std::string& value_string); 62 bool ParseFloat(const DataType& type, const std::string& value_string);
62 bool ParseDouble(const DataType& type, const std::string& value_string); 63 bool ParseDouble(const DataType& type, const std::string& value_string);
63 bool ParseBinarySequence(const DataType& type, 64 bool ParseBinarySequence(const DataType& type,
64 const std::string& value_string); 65 const std::string& value_string);
65 bool ParseDistance(const DataType& type, const std::string& value_string); 66 bool ParseDistance(const DataType& type, const std::string& value_string);
66 bool ParseAnchor(const DataType& type, const std::string& value_string); 67 bool ParseAnchor(const DataType& type, const std::string& value_string);
68 bool ParseHandles(const DataType& type, const std::string& value_string);
67 69
68 bool StartsWith(const Range& range, const char* prefix, size_t prefix_length); 70 bool StartsWith(const Range& range, const char* prefix, size_t prefix_length);
69 71
72 bool ConvertToUnsignedInteger(const std::string& value_string,
73 unsigned long long int* value);
74
70 template <typename T> 75 template <typename T>
71 void AppendData(T data) { 76 void AppendData(T data) {
72 size_t pos = parsed_input_->size(); 77 size_t pos = data_->size();
73 parsed_input_->resize(pos + sizeof(T)); 78 data_->resize(pos + sizeof(T));
74 memcpy(&(*parsed_input_)[pos], &data, sizeof(T)); 79 memcpy(&(*data_)[pos], &data, sizeof(T));
75 } 80 }
76 81
77 template <typename TargetType, typename InputType> 82 template <typename TargetType, typename InputType>
78 bool ConvertAndAppendData(InputType value) { 83 bool ConvertAndAppendData(InputType value) {
79 if (value > std::numeric_limits<TargetType>::max() || 84 if (value > std::numeric_limits<TargetType>::max() ||
80 value < std::numeric_limits<TargetType>::min()) { 85 value < std::numeric_limits<TargetType>::min()) {
81 return false; 86 return false;
82 } 87 }
83 AppendData(static_cast<TargetType>(value)); 88 AppendData(static_cast<TargetType>(value));
84 return true; 89 return true;
85 } 90 }
86 91
87 template <typename TargetType, typename InputType> 92 template <typename TargetType, typename InputType>
88 bool ConvertAndFillData(size_t pos, InputType value) { 93 bool ConvertAndFillData(size_t pos, InputType value) {
89 if (value > std::numeric_limits<TargetType>::max() || 94 if (value > std::numeric_limits<TargetType>::max() ||
90 value < std::numeric_limits<TargetType>::min()) { 95 value < std::numeric_limits<TargetType>::min()) {
91 return false; 96 return false;
92 } 97 }
93 TargetType target_value = static_cast<TargetType>(value); 98 TargetType target_value = static_cast<TargetType>(value);
94 assert(pos + sizeof(TargetType) <= parsed_input_->size()); 99 assert(pos + sizeof(TargetType) <= data_->size());
95 memcpy(&(*parsed_input_)[pos], &target_value, sizeof(TargetType)); 100 memcpy(&(*data_)[pos], &target_value, sizeof(TargetType));
96 return true; 101 return true;
97 } 102 }
98 103
99 static const DataType kDataTypes[]; 104 static const DataType kDataTypes[];
100 static const size_t kDataTypeCount; 105 static const size_t kDataTypeCount;
101 106
102 const std::string& input_; 107 const std::string& input_;
103 size_t input_cursor_; 108 size_t input_cursor_;
104 109
105 std::vector<uint8_t>* parsed_input_; 110 std::vector<uint8_t>* data_;
111 size_t* num_handles_;
106 std::string* error_message_; 112 std::string* error_message_;
107 113
108 std::map<std::string, PendingDistanceItem> pending_distance_items_; 114 std::map<std::string, PendingDistanceItem> pending_distance_items_;
109 }; 115 };
110 116
111 #define DATA_TYPE(name, data_size, parse_data_func) \ 117 #define DATA_TYPE(name, data_size, parse_data_func) \
112 {name, sizeof(name) - 1, data_size, parse_data_func} 118 {name, sizeof(name) - 1, data_size, parse_data_func}
113 119
114 const ValidationTestInputParser::DataType 120 const ValidationTestInputParser::DataType
115 ValidationTestInputParser::kDataTypes[] = { 121 ValidationTestInputParser::kDataTypes[] = {
116 DATA_TYPE("[u1]", 1, &ValidationTestInputParser::ParseUnsignedInteger), 122 DATA_TYPE("[u1]", 1, &ValidationTestInputParser::ParseUnsignedInteger),
117 DATA_TYPE("[u2]", 2, &ValidationTestInputParser::ParseUnsignedInteger), 123 DATA_TYPE("[u2]", 2, &ValidationTestInputParser::ParseUnsignedInteger),
118 DATA_TYPE("[u4]", 4, &ValidationTestInputParser::ParseUnsignedInteger), 124 DATA_TYPE("[u4]", 4, &ValidationTestInputParser::ParseUnsignedInteger),
119 DATA_TYPE("[u8]", 8, &ValidationTestInputParser::ParseUnsignedInteger), 125 DATA_TYPE("[u8]", 8, &ValidationTestInputParser::ParseUnsignedInteger),
120 DATA_TYPE("[s1]", 1, &ValidationTestInputParser::ParseSignedInteger), 126 DATA_TYPE("[s1]", 1, &ValidationTestInputParser::ParseSignedInteger),
121 DATA_TYPE("[s2]", 2, &ValidationTestInputParser::ParseSignedInteger), 127 DATA_TYPE("[s2]", 2, &ValidationTestInputParser::ParseSignedInteger),
122 DATA_TYPE("[s4]", 4, &ValidationTestInputParser::ParseSignedInteger), 128 DATA_TYPE("[s4]", 4, &ValidationTestInputParser::ParseSignedInteger),
123 DATA_TYPE("[s8]", 8, &ValidationTestInputParser::ParseSignedInteger), 129 DATA_TYPE("[s8]", 8, &ValidationTestInputParser::ParseSignedInteger),
124 DATA_TYPE("[b]", 1, &ValidationTestInputParser::ParseBinarySequence), 130 DATA_TYPE("[b]", 1, &ValidationTestInputParser::ParseBinarySequence),
125 DATA_TYPE("[f]", 4, &ValidationTestInputParser::ParseFloat), 131 DATA_TYPE("[f]", 4, &ValidationTestInputParser::ParseFloat),
126 DATA_TYPE("[d]", 8, &ValidationTestInputParser::ParseDouble), 132 DATA_TYPE("[d]", 8, &ValidationTestInputParser::ParseDouble),
127 DATA_TYPE("[dist4]", 4, &ValidationTestInputParser::ParseDistance), 133 DATA_TYPE("[dist4]", 4, &ValidationTestInputParser::ParseDistance),
128 DATA_TYPE("[dist8]", 8, &ValidationTestInputParser::ParseDistance), 134 DATA_TYPE("[dist8]", 8, &ValidationTestInputParser::ParseDistance),
129 DATA_TYPE("[anchr]", 0, &ValidationTestInputParser::ParseAnchor) 135 DATA_TYPE("[anchr]", 0, &ValidationTestInputParser::ParseAnchor),
136 DATA_TYPE("[handles]", 0, &ValidationTestInputParser::ParseHandles)
130 }; 137 };
131 138
132 const size_t ValidationTestInputParser::kDataTypeCount = 139 const size_t ValidationTestInputParser::kDataTypeCount =
133 sizeof(ValidationTestInputParser::kDataTypes) / 140 sizeof(ValidationTestInputParser::kDataTypes) /
134 sizeof(ValidationTestInputParser::kDataTypes[0]); 141 sizeof(ValidationTestInputParser::kDataTypes[0]);
135 142
136 ValidationTestInputParser::ValidationTestInputParser( 143 ValidationTestInputParser::ValidationTestInputParser(
137 const std::string& input, 144 const std::string& input,
138 std::vector<uint8_t>* parsed_input, 145 std::vector<uint8_t>* data,
146 size_t* num_handles,
139 std::string* error_message) 147 std::string* error_message)
140 : input_(input), 148 : input_(input),
141 input_cursor_(0), 149 input_cursor_(0),
142 parsed_input_(parsed_input), 150 data_(data),
151 num_handles_(num_handles),
143 error_message_(error_message) { 152 error_message_(error_message) {
144 assert(parsed_input_); 153 assert(data_);
154 assert(num_handles_);
145 assert(error_message_); 155 assert(error_message_);
146 parsed_input_->clear(); 156 data_->clear();
157 *num_handles_ = 0;
147 error_message_->clear(); 158 error_message_->clear();
148 } 159 }
149 160
150 ValidationTestInputParser::~ValidationTestInputParser() { 161 ValidationTestInputParser::~ValidationTestInputParser() {
151 } 162 }
152 163
153 bool ValidationTestInputParser::Run() { 164 bool ValidationTestInputParser::Run() {
154 Range range; 165 Range range;
155 bool result = true; 166 bool result = true;
156 while (result && GetNextItem(&range)) 167 while (result && GetNextItem(&range))
157 result = ParseItem(range); 168 result = ParseItem(range);
158 169
159 if (!result) { 170 if (!result) {
160 *error_message_ = "Error occurred when parsing " + 171 *error_message_ = "Error occurred when parsing " +
161 std::string(range.first, range.second); 172 std::string(range.first, range.second);
162 } else if (!pending_distance_items_.empty()) { 173 } else if (!pending_distance_items_.empty()) {
163 // We have parsed all the contents in |input_| successfully, but there are 174 // We have parsed all the contents in |input_| successfully, but there are
164 // unmatched dist4/8 items. 175 // unmatched dist4/8 items.
165 *error_message_ = "Error occurred when matching [dist4/8] and [anchr]."; 176 *error_message_ = "Error occurred when matching [dist4/8] and [anchr].";
166 result = false; 177 result = false;
167 } 178 }
168 if (!result) 179 if (!result) {
169 parsed_input_->clear(); 180 data_->clear();
170 else 181 *num_handles_ = 0;
182 } else {
171 assert(error_message_->empty()); 183 assert(error_message_->empty());
184 }
172 185
173 return result; 186 return result;
174 } 187 }
175 188
176 bool ValidationTestInputParser::GetNextItem(Range* range) { 189 bool ValidationTestInputParser::GetNextItem(Range* range) {
177 const char kWhitespaceChars[] = " \t\n\r"; 190 const char kWhitespaceChars[] = " \t\n\r";
178 const char kItemDelimiters[] = " \t\n\r/"; 191 const char kItemDelimiters[] = " \t\n\r/";
179 const char kEndOfLineChars[] = "\n\r"; 192 const char kEndOfLineChars[] = "\n\r";
180 while (true) { 193 while (true) {
181 // Skip leading whitespaces. 194 // Skip leading whitespaces.
(...skipping 30 matching lines...) Expand all
212 } 225 }
213 226
214 // "[u1]" is optional. 227 // "[u1]" is optional.
215 return ParseUnsignedInteger(kDataTypes[0], 228 return ParseUnsignedInteger(kDataTypes[0],
216 std::string(range.first, range.second)); 229 std::string(range.first, range.second));
217 } 230 }
218 231
219 bool ValidationTestInputParser::ParseUnsignedInteger( 232 bool ValidationTestInputParser::ParseUnsignedInteger(
220 const DataType& type, const std::string& value_string) { 233 const DataType& type, const std::string& value_string) {
221 unsigned long long int value; 234 unsigned long long int value;
222 const char* format = NULL; 235 if (!ConvertToUnsignedInteger(value_string, &value))
223 if (value_string.find_first_of("xX") != std::string::npos)
224 format = "%llx";
225 else
226 format = "%llu";
227 if (sscanf(value_string.c_str(), format, &value) != 1)
228 return false; 236 return false;
229 237
230 switch (type.data_size) { 238 switch (type.data_size) {
231 case 1: 239 case 1:
232 return ConvertAndAppendData<uint8_t>(value); 240 return ConvertAndAppendData<uint8_t>(value);
233 case 2: 241 case 2:
234 return ConvertAndAppendData<uint16_t>(value); 242 return ConvertAndAppendData<uint16_t>(value);
235 case 4: 243 case 4:
236 return ConvertAndAppendData<uint32_t>(value); 244 return ConvertAndAppendData<uint32_t>(value);
237 case 8: 245 case 8:
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 AppendData(value); 313 AppendData(value);
306 return true; 314 return true;
307 } 315 }
308 316
309 bool ValidationTestInputParser::ParseDistance(const DataType& type, 317 bool ValidationTestInputParser::ParseDistance(const DataType& type,
310 const std::string& value_string) { 318 const std::string& value_string) {
311 if (pending_distance_items_.find(value_string) != 319 if (pending_distance_items_.find(value_string) !=
312 pending_distance_items_.end()) 320 pending_distance_items_.end())
313 return false; 321 return false;
314 322
315 PendingDistanceItem item = {parsed_input_->size(), type.data_size}; 323 PendingDistanceItem item = {data_->size(), type.data_size};
316 parsed_input_->resize(parsed_input_->size() + type.data_size); 324 data_->resize(data_->size() + type.data_size);
317 pending_distance_items_[value_string] = item; 325 pending_distance_items_[value_string] = item;
318 326
319 return true; 327 return true;
320 } 328 }
321 329
322 bool ValidationTestInputParser::ParseAnchor(const DataType& type, 330 bool ValidationTestInputParser::ParseAnchor(const DataType& type,
323 const std::string& value_string) { 331 const std::string& value_string) {
324 std::map<std::string, PendingDistanceItem>::iterator iter = 332 std::map<std::string, PendingDistanceItem>::iterator iter =
325 pending_distance_items_.find(value_string); 333 pending_distance_items_.find(value_string);
326 if (iter == pending_distance_items_.end()) 334 if (iter == pending_distance_items_.end())
327 return false; 335 return false;
328 336
329 PendingDistanceItem dist_item = iter->second; 337 PendingDistanceItem dist_item = iter->second;
330 pending_distance_items_.erase(iter); 338 pending_distance_items_.erase(iter);
331 339
332 size_t distance = parsed_input_->size() - dist_item.pos; 340 size_t distance = data_->size() - dist_item.pos;
333 switch (dist_item.data_size) { 341 switch (dist_item.data_size) {
334 case 4: 342 case 4:
335 return ConvertAndFillData<uint32_t>(dist_item.pos, distance); 343 return ConvertAndFillData<uint32_t>(dist_item.pos, distance);
336 case 8: 344 case 8:
337 return ConvertAndFillData<uint64_t>(dist_item.pos, distance); 345 return ConvertAndFillData<uint64_t>(dist_item.pos, distance);
338 default: 346 default:
339 assert(false); 347 assert(false);
340 return false; 348 return false;
341 } 349 }
342 } 350 }
343 351
352 bool ValidationTestInputParser::ParseHandles(const DataType& type,
353 const std::string& value_string) {
354 // It should be the first item.
355 if (!data_->empty())
356 return false;
357
358 unsigned long long int value;
359 if (!ConvertToUnsignedInteger(value_string, &value))
360 return false;
361
362 if (value > std::numeric_limits<size_t>::max())
363 return false;
364
365 *num_handles_ = static_cast<size_t>(value);
366 return true;
367 }
368
344 bool ValidationTestInputParser::StartsWith(const Range& range, 369 bool ValidationTestInputParser::StartsWith(const Range& range,
345 const char* prefix, 370 const char* prefix,
346 size_t prefix_length) { 371 size_t prefix_length) {
347 if (static_cast<size_t>(range.second - range.first) < prefix_length) 372 if (static_cast<size_t>(range.second - range.first) < prefix_length)
348 return false; 373 return false;
349 374
350 return memcmp(range.first, prefix, prefix_length) == 0; 375 return memcmp(range.first, prefix, prefix_length) == 0;
351 } 376 }
352 377
378 bool ValidationTestInputParser::ConvertToUnsignedInteger(
379 const std::string& value_string,
380 unsigned long long int* value) {
381 const char* format = NULL;
382 if (value_string.find_first_of("xX") != std::string::npos)
383 format = "%llx";
384 else
385 format = "%llu";
386 return sscanf(value_string.c_str(), format, value) == 1;
387 }
388
353 } // namespace 389 } // namespace
354 390
355 bool ParseValidationTestInput(const std::string& input, 391 bool ParseValidationTestInput(const std::string& input,
356 std::vector<uint8_t>* parsed_input, 392 std::vector<uint8_t>* data,
393 size_t* num_handles,
357 std::string* error_message) { 394 std::string* error_message) {
358 ValidationTestInputParser parser(input, parsed_input, error_message); 395 ValidationTestInputParser parser(input, data, num_handles, error_message);
359 return parser.Run(); 396 return parser.Run();
360 } 397 }
361 398
362 } // namespace test 399 } // namespace test
363 } // namespace mojo 400 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/public/cpp/bindings/tests/validation_test_input_parser.h ('k') | mojo/public/cpp/bindings/tests/validation_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698