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

Side by Side Diff: test/cctest/test-strings.cc

Issue 11438046: Cleanup StringCharacterStream and add initial test cases. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Cleanup Created 8 years 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
« no previous file with comments | « src/objects-inl.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 2
3 // Check that we can traverse very deep stacks of ConsStrings using 3 // Check that we can traverse very deep stacks of ConsStrings using
4 // StringInputBuffer. Check that Get(int) works on very deep stacks 4 // StringInputBuffer. Check that Get(int) works on very deep stacks
5 // of ConsStrings. These operations may not be very fast, but they 5 // of ConsStrings. These operations may not be very fast, but they
6 // should be possible without getting errors due to too deep recursion. 6 // should be possible without getting errors due to too deep recursion.
7 7
8 #include <stdlib.h> 8 #include <stdlib.h>
9 9
10 #include "v8.h" 10 #include "v8.h"
11 11
12 #include "api.h" 12 #include "api.h"
13 #include "factory.h" 13 #include "factory.h"
14 #include "objects.h" 14 #include "objects.h"
15 #include "cctest.h" 15 #include "cctest.h"
16 #include "zone-inl.h" 16 #include "zone-inl.h"
17 17
18 unsigned int seed = 123; 18 // Adapted from http://en.wikipedia.org/wiki/Multiply-with-carry
19 class RandomNumberGenerator {
20 public:
21 RandomNumberGenerator() {
22 init();
23 }
19 24
20 static uint32_t gen() { 25 void init(uint32_t seed = 0x5688c73e) {
21 uint64_t z; 26 static const uint32_t phi = 0x9e3779b9;
22 z = seed; 27 c = 362436;
23 z *= 279470273; 28 i = kQSize-1;
24 z %= 4294967291U; 29 Q[0] = seed;
25 seed = static_cast<unsigned int>(z); 30 Q[1] = seed + phi;
26 return static_cast<uint32_t>(seed >> 16); 31 Q[2] = seed + phi + phi;
27 } 32 for (unsigned j = 3; j < kQSize; j++) {
33 Q[j] = Q[j - 3] ^ Q[j - 2] ^ phi ^ j;
34 }
35 }
36
37 uint32_t next() {
38 uint64_t a = 18782;
39 uint32_t r = 0xfffffffe;
40 i = (i + 1) & (kQSize-1);
41 uint64_t t = a * Q[i] + c;
42 c = (t >> 32);
43 uint32_t x = t + c;
44 if (x < c) {
45 x++;
46 c++;
47 }
48 return (Q[i] = r - x);
49 }
50
51 uint32_t next(int max) {
52 return next() % max;
53 }
54
55 bool next(double threshold) {
56 ASSERT(threshold >= 0.0 && threshold <= 1.0);
57 if (threshold == 1.0) return true;
58 if (threshold == 0.0) return false;
59 uint32_t value = next() % 100000;
60 return threshold > static_cast<double>(value)/100000.0;
61 }
62
63 private:
64 static const uint32_t kQSize = 4096;
65 uint32_t Q[kQSize];
66 uint32_t c;
67 uint32_t i;
68 };
28 69
29 70
30 using namespace v8::internal; 71 using namespace v8::internal;
31 72
32 static v8::Persistent<v8::Context> env; 73 static v8::Persistent<v8::Context> env;
33 74
34 75
35 static void InitializeVM() { 76 static void InitializeVM() {
36 if (env.IsEmpty()) { 77 if (env.IsEmpty()) {
37 v8::HandleScope scope; 78 v8::HandleScope scope;
38 const char* extensions[] = { "v8/print" }; 79 const char* extensions[] = { "v8/print" };
39 v8::ExtensionConfiguration config(1, extensions); 80 v8::ExtensionConfiguration config(1, extensions);
40 env = v8::Context::New(&config); 81 env = v8::Context::New(&config);
41 } 82 }
42 v8::HandleScope scope; 83 v8::HandleScope scope;
43 env->Enter(); 84 env->Enter();
44 } 85 }
45 86
46 87
47 static const int NUMBER_OF_BUILDING_BLOCKS = 128; 88 static const int NUMBER_OF_BUILDING_BLOCKS = 256;
48 static const int DEEP_DEPTH = 8 * 1024; 89 static const int DEEP_DEPTH = 8 * 1024;
49 static const int SUPER_DEEP_DEPTH = 80 * 1024; 90 static const int SUPER_DEEP_DEPTH = 80 * 1024;
50 91
51 92
52 class Resource: public v8::String::ExternalStringResource, 93 class Resource: public v8::String::ExternalStringResource,
53 public ZoneObject { 94 public ZoneObject {
54 public: 95 public:
55 explicit Resource(Vector<const uc16> string): data_(string.start()) { 96 explicit Resource(Vector<const uc16> string): data_(string.start()) {
56 length_ = string.length(); 97 length_ = string.length();
57 } 98 }
(...skipping 14 matching lines...) Expand all
72 } 113 }
73 virtual const char* data() const { return data_; } 114 virtual const char* data() const { return data_; }
74 virtual size_t length() const { return length_; } 115 virtual size_t length() const { return length_; }
75 116
76 private: 117 private:
77 const char* data_; 118 const char* data_;
78 size_t length_; 119 size_t length_;
79 }; 120 };
80 121
81 122
82 static void InitializeBuildingBlocks( 123 static void InitializeBuildingBlocks(Handle<String>* building_blocks,
83 Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS]) { 124 int bb_length,
125 bool long_blocks,
126 RandomNumberGenerator* rng) {
84 // A list of pointers that we don't have any interest in cleaning up. 127 // A list of pointers that we don't have any interest in cleaning up.
85 // If they are reachable from a root then leak detection won't complain. 128 // If they are reachable from a root then leak detection won't complain.
86 Zone* zone = Isolate::Current()->runtime_zone(); 129 Zone* zone = Isolate::Current()->runtime_zone();
87 for (int i = 0; i < NUMBER_OF_BUILDING_BLOCKS; i++) { 130 for (int i = 0; i < bb_length; i++) {
88 int len = gen() % 16; 131 int len = rng->next(16);
89 if (len > 14) { 132 int slice_head_chars = 0;
133 int slice_tail_chars = 0;
134 int slice_depth = 0;
135 for (int j = 0; j < 3; j++) {
136 if (rng->next(0.35)) slice_depth++;
137 }
138 // Must truncate something for a slice string. Loop until
139 // at least one end will be sliced.
140 while (slice_head_chars == 0 && slice_tail_chars == 0) {
141 slice_head_chars = rng->next(15);
142 slice_tail_chars = rng->next(12);
143 }
144 if (long_blocks) {
145 // Generate building blocks which will never be merged
146 len += ConsString::kMinLength + 1;
147 } else if (len > 14) {
90 len += 1234; 148 len += 1234;
91 } 149 }
92 switch (gen() % 4) { 150 // Don't slice 0 length strings.
151 if (len == 0) slice_depth = 0;
152 int slice_length = slice_depth*(slice_head_chars + slice_tail_chars);
153 len += slice_length;
154 switch (rng->next(4)) {
93 case 0: { 155 case 0: {
94 uc16 buf[2000]; 156 uc16 buf[2000];
95 for (int j = 0; j < len; j++) { 157 for (int j = 0; j < len; j++) {
96 buf[j] = gen() % 65536; 158 buf[j] = rng->next(0x10000);
97 } 159 }
98 building_blocks[i] = 160 building_blocks[i] =
99 FACTORY->NewStringFromTwoByte(Vector<const uc16>(buf, len)); 161 FACTORY->NewStringFromTwoByte(Vector<const uc16>(buf, len));
100 for (int j = 0; j < len; j++) { 162 for (int j = 0; j < len; j++) {
101 CHECK_EQ(buf[j], building_blocks[i]->Get(j)); 163 CHECK_EQ(buf[j], building_blocks[i]->Get(j));
102 } 164 }
103 break; 165 break;
104 } 166 }
105 case 1: { 167 case 1: {
106 char buf[2000]; 168 char buf[2000];
107 for (int j = 0; j < len; j++) { 169 for (int j = 0; j < len; j++) {
108 buf[j] = gen() % 128; 170 buf[j] = rng->next(0x80);
109 } 171 }
110 building_blocks[i] = 172 building_blocks[i] =
111 FACTORY->NewStringFromAscii(Vector<const char>(buf, len)); 173 FACTORY->NewStringFromAscii(Vector<const char>(buf, len));
112 for (int j = 0; j < len; j++) { 174 for (int j = 0; j < len; j++) {
113 CHECK_EQ(buf[j], building_blocks[i]->Get(j)); 175 CHECK_EQ(buf[j], building_blocks[i]->Get(j));
114 } 176 }
115 break; 177 break;
116 } 178 }
117 case 2: { 179 case 2: {
118 uc16* buf = zone->NewArray<uc16>(len); 180 uc16* buf = zone->NewArray<uc16>(len);
119 for (int j = 0; j < len; j++) { 181 for (int j = 0; j < len; j++) {
120 buf[j] = gen() % 65536; 182 buf[j] = rng->next(0x10000);
121 } 183 }
122 Resource* resource = new(zone) Resource(Vector<const uc16>(buf, len)); 184 Resource* resource = new(zone) Resource(Vector<const uc16>(buf, len));
123 building_blocks[i] = FACTORY->NewExternalStringFromTwoByte(resource); 185 building_blocks[i] = FACTORY->NewExternalStringFromTwoByte(resource);
124 for (int j = 0; j < len; j++) { 186 for (int j = 0; j < len; j++) {
125 CHECK_EQ(buf[j], building_blocks[i]->Get(j)); 187 CHECK_EQ(buf[j], building_blocks[i]->Get(j));
126 } 188 }
127 break; 189 break;
128 } 190 }
129 case 3: { 191 case 3: {
130 char* buf = NewArray<char>(len); 192 char* buf = zone->NewArray<char>(len);
131 for (int j = 0; j < len; j++) { 193 for (int j = 0; j < len; j++) {
132 buf[j] = gen() % 128; 194 buf[j] = rng->next(128);
133 } 195 }
134 building_blocks[i] = 196 AsciiResource* resource =
135 FACTORY->NewStringFromAscii(Vector<const char>(buf, len)); 197 new(zone) AsciiResource(Vector<const char>(buf, len));
198 building_blocks[i] = FACTORY->NewExternalStringFromAscii(resource);
136 for (int j = 0; j < len; j++) { 199 for (int j = 0; j < len; j++) {
137 CHECK_EQ(buf[j], building_blocks[i]->Get(j)); 200 CHECK_EQ(buf[j], building_blocks[i]->Get(j));
138 } 201 }
139 DeleteArray<char>(buf);
140 break; 202 break;
141 } 203 }
142 } 204 }
205 for (int j = slice_depth; j > 0; j--) {
206 building_blocks[i] = FACTORY->NewSubString(
207 building_blocks[i],
208 slice_head_chars,
209 building_blocks[i]->length() - slice_tail_chars);
210 }
211 CHECK(len == building_blocks[i]->length() + slice_length);
143 } 212 }
144 } 213 }
145 214
146 215
147 static Handle<String> ConstructLeft( 216 static Handle<String> ConstructLeft(
148 Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS], 217 Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS],
149 int depth) { 218 int depth) {
150 Handle<String> answer = FACTORY->NewStringFromAscii(CStrVector("")); 219 Handle<String> answer = FACTORY->NewStringFromAscii(CStrVector(""));
151 for (int i = 0; i < depth; i++) { 220 for (int i = 0; i < depth; i++) {
152 answer = FACTORY->NewConsString( 221 answer = FACTORY->NewConsString(
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
191 } 260 }
192 261
193 262
194 static Handle<String> ConstructBalanced( 263 static Handle<String> ConstructBalanced(
195 Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS]) { 264 Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS]) {
196 return ConstructBalancedHelper(building_blocks, 0, DEEP_DEPTH); 265 return ConstructBalancedHelper(building_blocks, 0, DEEP_DEPTH);
197 } 266 }
198 267
199 268
200 static StringInputBuffer buffer; 269 static StringInputBuffer buffer;
201 270 static ConsStringIteratorOp cons_string_iterator_op_1;
271 static ConsStringIteratorOp cons_string_iterator_op_2;
202 272
203 static void Traverse(Handle<String> s1, Handle<String> s2) { 273 static void Traverse(Handle<String> s1, Handle<String> s2) {
204 int i = 0; 274 int i = 0;
205 buffer.Reset(*s1); 275 buffer.Reset(*s1);
276 StringCharacterStream character_stream_1(*s1, 0, &cons_string_iterator_op_1);
277 StringCharacterStream character_stream_2(*s2, 0, &cons_string_iterator_op_2);
206 StringInputBuffer buffer2(*s2); 278 StringInputBuffer buffer2(*s2);
207 while (buffer.has_more()) { 279 while (buffer.has_more()) {
208 CHECK(buffer2.has_more()); 280 CHECK(buffer2.has_more());
281 CHECK(character_stream_1.HasMore());
282 CHECK(character_stream_2.HasMore());
209 uint16_t c = buffer.GetNext(); 283 uint16_t c = buffer.GetNext();
210 CHECK_EQ(c, buffer2.GetNext()); 284 CHECK_EQ(c, buffer2.GetNext());
285 CHECK_EQ(c, character_stream_1.GetNext());
286 CHECK_EQ(c, character_stream_2.GetNext());
211 i++; 287 i++;
212 } 288 }
289 CHECK(!character_stream_1.HasMore());
290 CHECK(!character_stream_2.HasMore());
213 CHECK_EQ(s1->length(), i); 291 CHECK_EQ(s1->length(), i);
214 CHECK_EQ(s2->length(), i); 292 CHECK_EQ(s2->length(), i);
215 } 293 }
216 294
217 295
218 static void TraverseFirst(Handle<String> s1, Handle<String> s2, int chars) { 296 static void TraverseFirst(Handle<String> s1, Handle<String> s2, int chars) {
219 int i = 0; 297 int i = 0;
220 buffer.Reset(*s1); 298 buffer.Reset(*s1);
221 StringInputBuffer buffer2(*s2); 299 StringInputBuffer buffer2(*s2);
300 StringCharacterStream character_stream_1(*s1, 0, &cons_string_iterator_op_1);
301 StringCharacterStream character_stream_2(*s2, 0, &cons_string_iterator_op_2);
222 while (buffer.has_more() && i < chars) { 302 while (buffer.has_more() && i < chars) {
223 CHECK(buffer2.has_more()); 303 CHECK(buffer2.has_more());
304 CHECK(character_stream_1.HasMore());
305 CHECK(character_stream_2.HasMore());
224 uint16_t c = buffer.GetNext(); 306 uint16_t c = buffer.GetNext();
225 CHECK_EQ(c, buffer2.GetNext()); 307 CHECK_EQ(c, buffer2.GetNext());
308 CHECK_EQ(c, character_stream_1.GetNext());
309 CHECK_EQ(c, character_stream_2.GetNext());
226 i++; 310 i++;
227 } 311 }
228 s1->Get(s1->length() - 1); 312 s1->Get(s1->length() - 1);
229 s2->Get(s2->length() - 1); 313 s2->Get(s2->length() - 1);
230 } 314 }
231 315
232 316
233 TEST(Traverse) { 317 TEST(Traverse) {
234 printf("TestTraverse\n"); 318 printf("TestTraverse\n");
235 InitializeVM(); 319 InitializeVM();
236 v8::HandleScope scope; 320 v8::HandleScope scope;
237 Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS]; 321 Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS];
238 ZoneScope zone(Isolate::Current()->runtime_zone(), DELETE_ON_EXIT); 322 ZoneScope zone(Isolate::Current()->runtime_zone(), DELETE_ON_EXIT);
239 InitializeBuildingBlocks(building_blocks); 323 RandomNumberGenerator rng;
324 rng.init();
325 InitializeBuildingBlocks(
326 building_blocks, NUMBER_OF_BUILDING_BLOCKS, false, &rng);
240 Handle<String> flat = ConstructBalanced(building_blocks); 327 Handle<String> flat = ConstructBalanced(building_blocks);
241 FlattenString(flat); 328 FlattenString(flat);
242 Handle<String> left_asymmetric = ConstructLeft(building_blocks, DEEP_DEPTH); 329 Handle<String> left_asymmetric = ConstructLeft(building_blocks, DEEP_DEPTH);
243 Handle<String> right_asymmetric = ConstructRight(building_blocks, DEEP_DEPTH); 330 Handle<String> right_asymmetric = ConstructRight(building_blocks, DEEP_DEPTH);
244 Handle<String> symmetric = ConstructBalanced(building_blocks); 331 Handle<String> symmetric = ConstructBalanced(building_blocks);
245 printf("1\n"); 332 printf("1\n");
246 Traverse(flat, symmetric); 333 Traverse(flat, symmetric);
247 printf("2\n"); 334 printf("2\n");
248 Traverse(flat, left_asymmetric); 335 Traverse(flat, left_asymmetric);
249 printf("3\n"); 336 printf("3\n");
(...skipping 18 matching lines...) Expand all
268 printf("14\n"); 355 printf("14\n");
269 FlattenString(symmetric); 356 FlattenString(symmetric);
270 printf("15\n"); 357 printf("15\n");
271 Traverse(flat, symmetric); 358 Traverse(flat, symmetric);
272 printf("16\n"); 359 printf("16\n");
273 FlattenString(left_deep_asymmetric); 360 FlattenString(left_deep_asymmetric);
274 printf("18\n"); 361 printf("18\n");
275 } 362 }
276 363
277 364
365 class ConsStringStats {
366 public:
367 ConsStringStats() {
368 Reset();
369 }
370 void Reset();
371 void VerifyEqual(const ConsStringStats& that) const;
372 unsigned leaves_;
373 unsigned empty_leaves_;
374 unsigned chars_;
375 unsigned left_traversals_;
376 unsigned right_traversals_;
377 private:
378 DISALLOW_COPY_AND_ASSIGN(ConsStringStats);
379 };
380
381
382 void ConsStringStats::Reset() {
383 leaves_ = 0;
384 empty_leaves_ = 0;
385 chars_ = 0;
386 left_traversals_ = 0;
387 right_traversals_ = 0;
388 }
389
390
391 void ConsStringStats::VerifyEqual(const ConsStringStats& that) const {
392 CHECK(this->leaves_ == that.leaves_);
393 CHECK(this->empty_leaves_ == that.empty_leaves_);
394 CHECK(this->chars_ == that.chars_);
395 CHECK(this->left_traversals_ == that.left_traversals_);
396 CHECK(this->right_traversals_ == that.right_traversals_);
397 }
398
399
400 class ConsStringGenerationData {
401 public:
402 ConsStringGenerationData();
403 void Reset();
404 // Input variables.
405 double early_termination_threshold_;
406 double leftness_;
407 double rightness_;
408 double empty_leaf_threshold_;
409 unsigned max_leaves_;
410 // Cached data.
411 Handle<String> building_blocks_[NUMBER_OF_BUILDING_BLOCKS];
412 String* empty_string_;
413 RandomNumberGenerator rng_;
414 // Stats.
415 ConsStringStats stats_;
416 unsigned early_terminations_;
417 private:
418 DISALLOW_COPY_AND_ASSIGN(ConsStringGenerationData);
419 };
420
421
422 ConsStringGenerationData::ConsStringGenerationData() {
423 rng_.init();
424 InitializeBuildingBlocks(
425 building_blocks_, NUMBER_OF_BUILDING_BLOCKS, true, &rng_);
426 empty_string_ = Isolate::Current()->heap()->empty_string();
427 Reset();
428 }
429
430
431 void ConsStringGenerationData::Reset() {
432 early_termination_threshold_ = 0.01;
433 leftness_ = 0.75;
434 rightness_ = 0.75;
435 empty_leaf_threshold_ = 0.02;
436 max_leaves_ = 1000;
437 stats_.Reset();
438 early_terminations_ = 0;
439 }
440
441
442 void VerifyConsString(ConsString* cons_string, ConsStringStats* stats) {
443 int left_length = cons_string->first()->length();
444 int right_length = cons_string->second()->length();
445 CHECK(cons_string->length() == left_length + right_length);
446 // Check left side.
447 if (cons_string->first()->IsConsString()) {
448 stats->left_traversals_++;
449 VerifyConsString(ConsString::cast(cons_string->first()), stats);
450 } else {
451 CHECK_NE(left_length, 0);
452 stats->leaves_++;
453 stats->chars_ += left_length;
454 }
455 // Check right side.
456 if (cons_string->second()->IsConsString()) {
457 stats->right_traversals_++;
458 VerifyConsString(ConsString::cast(cons_string->second()), stats);
459 } else {
460 if (right_length == 0) stats->empty_leaves_++;
461 stats->leaves_++;
462 stats->chars_ += right_length;
463 }
464 }
465
466
467 void VerifyConsStringWithOperator(
468 ConsString* cons_string, ConsStringStats* stats) {
469 // Init op.
470 ConsStringIteratorOp op;
471 op.Reset();
472 // Use response for initial search and on blown stack.
473 ConsStringIteratorOp::ContinueResponse response;
474 response.string_ = cons_string;
475 response.offset_ = 0;
476 response.type_ = cons_string->map()->instance_type();
477 response.length_ = (uint32_t) cons_string->length();
478 while (true) {
479 String* string = op.Operate(ConsString::cast(response.string_),
480 &response.offset_,
481 &response.type_,
482 &response.length_);
483 CHECK(string != NULL);
484 while (true) {
485 // Accumulate stats.
486 stats->leaves_++;
487 stats->chars_ += string->length();
488 // Check for completion.
489 bool keep_going_fast_check = op.HasMore();
490 bool keep_going = op.ContinueOperation(&response);
491 if (!keep_going) return;
492 // Verify no false positives for fast check.
493 CHECK(keep_going_fast_check);
494 CHECK(response.string_ != NULL);
495 // Blew stack. Restart outer loop.
496 if (response.string_->IsConsString()) break;
497 string = response.string_;
498 }
499 };
500 }
501
502
503 void VerifyConsString(Handle<String> root, ConsStringGenerationData* data) {
504 // Verify basic data.
505 CHECK(root->IsConsString());
506 CHECK((unsigned)root->length() == data->stats_.chars_);
507 // Recursive verify.
508 ConsStringStats stats;
509 VerifyConsString(ConsString::cast(*root), &stats);
510 stats.VerifyEqual(data->stats_);
511 // Iteratively verify.
512 stats.Reset();
513 VerifyConsStringWithOperator(ConsString::cast(*root), &stats);
514 // Don't see these. Must copy over.
515 stats.empty_leaves_ = data->stats_.empty_leaves_;
516 stats.left_traversals_ = data->stats_.left_traversals_;
517 stats.right_traversals_ = data->stats_.right_traversals_;
518 // Adjust total leaves to compensate.
519 stats.leaves_ += stats.empty_leaves_;
520 stats.VerifyEqual(data->stats_);
521 }
522
523
524 static Handle<String> ConstructRandomString(ConsStringGenerationData* data,
525 unsigned max_recursion) {
526 // Compute termination characteristics.
527 bool terminate = false;
528 bool flat = data->rng_.next(data->empty_leaf_threshold_);
529 bool terminate_early = data->rng_.next(data->early_termination_threshold_);
530 if (terminate_early) data->early_terminations_++;
531 // The obvious condition.
532 terminate |= max_recursion == 0;
533 // Flat cons string terminate by definition.
534 terminate |= flat;
535 // Cap for max leaves.
536 terminate |= data->stats_.leaves_ >= data->max_leaves_;
537 // Roll the dice.
538 terminate |= terminate_early;
539 // Compute termination characteristics for each side.
540 bool terminate_left = terminate || !data->rng_.next(data->leftness_);
541 bool terminate_right = terminate || !data->rng_.next(data->rightness_);
542 // Generate left string.
543 Handle<String> left;
544 if (terminate_left) {
545 left = data->building_blocks_[data->rng_.next(NUMBER_OF_BUILDING_BLOCKS)];
546 data->stats_.leaves_++;
547 data->stats_.chars_ += left->length();
548 } else {
549 left = ConstructRandomString(data, max_recursion - 1);
550 data->stats_.left_traversals_++;
551 }
552 // Generate right string.
553 Handle<String> right;
554 if (terminate_right) {
555 right = data->building_blocks_[data->rng_.next(NUMBER_OF_BUILDING_BLOCKS)];
556 data->stats_.leaves_++;
557 data->stats_.chars_ += right->length();
558 } else {
559 right = ConstructRandomString(data, max_recursion - 1);
560 data->stats_.right_traversals_++;
561 }
562 // Build the cons string.
563 Handle<String> root = FACTORY->NewConsString(left, right);
564 CHECK(root->IsConsString() && !root->IsFlat());
565 // Special work needed for flat string.
566 if (flat) {
567 data->stats_.empty_leaves_++;
568 FlattenString(root);
569 CHECK(root->IsConsString() && root->IsFlat());
570 }
571 return root;
572 }
573
574
575 static const int kCharacterStreamRandomCases = 150;
576 static const int kCharacterStreamEdgeCases =
577 kCharacterStreamRandomCases + 5;
578
579
580 static Handle<String> BuildConsStrings(int testCase,
581 ConsStringGenerationData* data) {
582 // For random constructions, need to reset the generator.
583 data->rng_.init();
584 for (int j = 0; j < testCase * 50; j++) {
585 data->rng_.next();
586 }
587 Handle<String> string;
588 switch (testCase) {
589 case 0:
590 return ConstructBalanced(data->building_blocks_);
591 case 1:
592 return ConstructLeft(data->building_blocks_, DEEP_DEPTH);
593 case 2:
594 return ConstructRight(data->building_blocks_, DEEP_DEPTH);
595 case 3:
596 return ConstructLeft(data->building_blocks_, 10);
597 case 4:
598 return ConstructRight(data->building_blocks_, 10);
599 case 5:
600 return FACTORY->NewConsString(
601 data->building_blocks_[0], data->building_blocks_[1]);
602 default:
603 if (testCase >= kCharacterStreamEdgeCases) {
604 CHECK(false);
605 return string;
606 }
607 // Random test case.
608 data->Reset();
609 string = ConstructRandomString(data, 200);
610 AssertNoAllocation no_alloc;
611 VerifyConsString(string, data);
612 #ifdef DEBUG
613 printf(
614 "%s: [%d], %s: [%d], %s: [%d], %s: [%d], %s: [%d], %s: [%d]\n",
615 "leaves", data->stats_.leaves_,
616 "empty", data->stats_.empty_leaves_,
617 "chars", data->stats_.chars_,
618 "lefts", data->stats_.left_traversals_,
619 "rights", data->stats_.right_traversals_,
620 "early_terminations", data->early_terminations_);
621 #endif
622 return string;
623 }
624 }
625
626
627 static void VerifyCharacterStream(
628 String* flat_string, String* cons_string) {
629 // Do not want to test ConString traversal on flat string.
630 CHECK(flat_string->IsFlat());
631 CHECK(!flat_string->IsConsString());
632 CHECK(cons_string->IsConsString());
633 // TODO(dcarney) Test stream reset as well.
634 int length = flat_string->length();
635 // Iterate start search in multiple places in the string.
636 int outer_iterations = length > 20 ? 20 : length;
637 for (int j = 0; j <= outer_iterations; j++) {
638 int offset = static_cast<double>(length)*j/outer_iterations;
639 if (offset < 0) offset = 0;
640 // Want to test the offset == length case.
641 if (offset > length) offset = length;
642 StringCharacterStream flat_stream(
643 flat_string, (unsigned) offset, &cons_string_iterator_op_1);
644 StringCharacterStream cons_stream(
645 cons_string, (unsigned) offset, &cons_string_iterator_op_2);
646 for (int i = offset; i < length; i++) {
647 uint16_t c = flat_string->Get(i);
648 CHECK(flat_stream.HasMore());
649 CHECK(cons_stream.HasMore());
650 CHECK_EQ(c, flat_stream.GetNext());
651 CHECK_EQ(c, cons_stream.GetNext());
652 }
653 CHECK(!flat_stream.HasMore());
654 CHECK(!cons_stream.HasMore());
655 }
656 }
657
658
659 TEST(StringCharacterStreamEdgeCases) {
660 printf("TestStringCharacterStreamEdgeCases\n");
661 InitializeVM();
662 Isolate* isolate = Isolate::Current();
663 HandleScope outer_scope(isolate);
664 ZoneScope zone(Isolate::Current()->runtime_zone(), DELETE_ON_EXIT);
665 ConsStringGenerationData data;
666 for (int i = 0; i < kCharacterStreamEdgeCases; i++) {
667 printf("%d\n", i);
668 isolate->heap()->CollectAllGarbage(
669 Heap::kNoGCFlags, "must not allocate in loop");
670 AlwaysAllocateScope always_allocate;
671 HandleScope inner_scope(isolate);
672 Handle<String> cons_string = BuildConsStrings(i, &data);
673 Handle<String> flat_string = BuildConsStrings(i, &data);
674 FlattenString(flat_string);
675 AssertNoAllocation no_alloc;
676 CHECK(flat_string->IsConsString() && flat_string->IsFlat());
677 VerifyCharacterStream(ConsString::cast(*flat_string)->first(),
678 *cons_string);
679 }
680 }
681
682
278 static const int DEEP_ASCII_DEPTH = 100000; 683 static const int DEEP_ASCII_DEPTH = 100000;
279 684
280 685
281 TEST(DeepAscii) { 686 TEST(DeepAscii) {
282 printf("TestDeepAscii\n"); 687 printf("TestDeepAscii\n");
283 InitializeVM(); 688 InitializeVM();
284 v8::HandleScope scope; 689 v8::HandleScope scope;
285 690
286 char* foo = NewArray<char>(DEEP_ASCII_DEPTH); 691 char* foo = NewArray<char>(DEEP_ASCII_DEPTH);
287 for (int i = 0; i < DEEP_ASCII_DEPTH; i++) { 692 for (int i = 0; i < DEEP_ASCII_DEPTH; i++) {
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after
708 1113
709 v8::Local<v8::String> expected = v8_str("ascii\x80only\x80string\x80"); 1114 v8::Local<v8::String> expected = v8_str("ascii\x80only\x80string\x80");
710 CHECK(expected->Equals(result)); 1115 CHECK(expected->Equals(result));
711 } 1116 }
712 1117
713 1118
714 TEST(IsAscii) { 1119 TEST(IsAscii) {
715 CHECK(String::IsAscii(static_cast<char*>(NULL), 0)); 1120 CHECK(String::IsAscii(static_cast<char*>(NULL), 0));
716 CHECK(String::IsAscii(static_cast<uc16*>(NULL), 0)); 1121 CHECK(String::IsAscii(static_cast<uc16*>(NULL), 0));
717 } 1122 }
OLDNEW
« no previous file with comments | « src/objects-inl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698