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

Unified Diff: test/cctest/test-strings.cc

Issue 11548023: Cleanup tests for StringCharacterStream (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: test/cctest/test-strings.cc
diff --git a/test/cctest/test-strings.cc b/test/cctest/test-strings.cc
index 26b73392cc92415115d70f1351d3d2b41030b336..4fb32d5b861ade3bebd27cf5f5ac4111d4a67887 100644
--- a/test/cctest/test-strings.cc
+++ b/test/cctest/test-strings.cc
@@ -85,7 +85,6 @@ static void InitializeVM() {
}
-static const int NUMBER_OF_BUILDING_BLOCKS = 256;
static const int DEEP_DEPTH = 8 * 1024;
static const int SUPER_DEEP_DEPTH = 80 * 1024;
@@ -191,7 +190,7 @@ static void InitializeBuildingBlocks(Handle<String>* building_blocks,
case 3: {
char* buf = zone->NewArray<char>(len);
for (int j = 0; j < len; j++) {
- buf[j] = rng->next(128);
+ buf[j] = rng->next(0x80);
}
AsciiResource* resource =
new(zone) AsciiResource(Vector<const char>(buf, len));
@@ -213,155 +212,6 @@ static void InitializeBuildingBlocks(Handle<String>* building_blocks,
}
-static Handle<String> ConstructLeft(
- Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS],
- int depth) {
- Handle<String> answer = FACTORY->NewStringFromAscii(CStrVector(""));
- for (int i = 0; i < depth; i++) {
- answer = FACTORY->NewConsString(
- answer,
- building_blocks[i % NUMBER_OF_BUILDING_BLOCKS]);
- }
- return answer;
-}
-
-
-static Handle<String> ConstructRight(
- Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS],
- int depth) {
- Handle<String> answer = FACTORY->NewStringFromAscii(CStrVector(""));
- for (int i = depth - 1; i >= 0; i--) {
- answer = FACTORY->NewConsString(
- building_blocks[i % NUMBER_OF_BUILDING_BLOCKS],
- answer);
- }
- return answer;
-}
-
-
-static Handle<String> ConstructBalancedHelper(
- Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS],
- int from,
- int to) {
- CHECK(to > from);
- if (to - from == 1) {
- return building_blocks[from % NUMBER_OF_BUILDING_BLOCKS];
- }
- if (to - from == 2) {
- return FACTORY->NewConsString(
- building_blocks[from % NUMBER_OF_BUILDING_BLOCKS],
- building_blocks[(from+1) % NUMBER_OF_BUILDING_BLOCKS]);
- }
- Handle<String> part1 =
- ConstructBalancedHelper(building_blocks, from, from + ((to - from) / 2));
- Handle<String> part2 =
- ConstructBalancedHelper(building_blocks, from + ((to - from) / 2), to);
- return FACTORY->NewConsString(part1, part2);
-}
-
-
-static Handle<String> ConstructBalanced(
- Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS]) {
- return ConstructBalancedHelper(building_blocks, 0, DEEP_DEPTH);
-}
-
-
-static StringInputBuffer buffer;
-static ConsStringIteratorOp cons_string_iterator_op_1;
-static ConsStringIteratorOp cons_string_iterator_op_2;
-
-static void Traverse(Handle<String> s1, Handle<String> s2) {
- int i = 0;
- buffer.Reset(*s1);
- StringCharacterStream character_stream_1(*s1, 0, &cons_string_iterator_op_1);
- StringCharacterStream character_stream_2(*s2, 0, &cons_string_iterator_op_2);
- StringInputBuffer buffer2(*s2);
- while (buffer.has_more()) {
- CHECK(buffer2.has_more());
- CHECK(character_stream_1.HasMore());
- CHECK(character_stream_2.HasMore());
- uint16_t c = buffer.GetNext();
- CHECK_EQ(c, buffer2.GetNext());
- CHECK_EQ(c, character_stream_1.GetNext());
- CHECK_EQ(c, character_stream_2.GetNext());
- i++;
- }
- CHECK(!character_stream_1.HasMore());
- CHECK(!character_stream_2.HasMore());
- CHECK_EQ(s1->length(), i);
- CHECK_EQ(s2->length(), i);
-}
-
-
-static void TraverseFirst(Handle<String> s1, Handle<String> s2, int chars) {
- int i = 0;
- buffer.Reset(*s1);
- StringInputBuffer buffer2(*s2);
- StringCharacterStream character_stream_1(*s1, 0, &cons_string_iterator_op_1);
- StringCharacterStream character_stream_2(*s2, 0, &cons_string_iterator_op_2);
- while (buffer.has_more() && i < chars) {
- CHECK(buffer2.has_more());
- CHECK(character_stream_1.HasMore());
- CHECK(character_stream_2.HasMore());
- uint16_t c = buffer.GetNext();
- CHECK_EQ(c, buffer2.GetNext());
- CHECK_EQ(c, character_stream_1.GetNext());
- CHECK_EQ(c, character_stream_2.GetNext());
- i++;
- }
- s1->Get(s1->length() - 1);
- s2->Get(s2->length() - 1);
-}
-
-
-TEST(Traverse) {
- printf("TestTraverse\n");
- InitializeVM();
- v8::HandleScope scope;
- Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS];
- ZoneScope zone(Isolate::Current()->runtime_zone(), DELETE_ON_EXIT);
- RandomNumberGenerator rng;
- rng.init();
- InitializeBuildingBlocks(
- building_blocks, NUMBER_OF_BUILDING_BLOCKS, false, &rng);
- Handle<String> flat = ConstructBalanced(building_blocks);
- FlattenString(flat);
- Handle<String> left_asymmetric = ConstructLeft(building_blocks, DEEP_DEPTH);
- Handle<String> right_asymmetric = ConstructRight(building_blocks, DEEP_DEPTH);
- Handle<String> symmetric = ConstructBalanced(building_blocks);
- printf("1\n");
- Traverse(flat, symmetric);
- printf("2\n");
- Traverse(flat, left_asymmetric);
- printf("3\n");
- Traverse(flat, right_asymmetric);
- printf("4\n");
- Handle<String> left_deep_asymmetric =
- ConstructLeft(building_blocks, SUPER_DEEP_DEPTH);
- Handle<String> right_deep_asymmetric =
- ConstructRight(building_blocks, SUPER_DEEP_DEPTH);
- printf("5\n");
- TraverseFirst(left_asymmetric, left_deep_asymmetric, 1050);
- printf("6\n");
- TraverseFirst(left_asymmetric, right_deep_asymmetric, 65536);
- printf("7\n");
- FlattenString(left_asymmetric);
- printf("10\n");
- Traverse(flat, left_asymmetric);
- printf("11\n");
- FlattenString(right_asymmetric);
- printf("12\n");
- Traverse(flat, right_asymmetric);
- printf("14\n");
- FlattenString(symmetric);
- printf("15\n");
- Traverse(flat, symmetric);
- printf("16\n");
- FlattenString(left_deep_asymmetric);
- printf("18\n");
-}
-
-
class ConsStringStats {
public:
ConsStringStats() {
@@ -399,8 +249,11 @@ void ConsStringStats::VerifyEqual(const ConsStringStats& that) const {
class ConsStringGenerationData {
public:
- ConsStringGenerationData();
+ static const int kNumberOfBuildingBlocks = 256;
+ explicit ConsStringGenerationData(bool long_blocks);
void Reset();
+ inline Handle<String> block(int offset);
+ inline Handle<String> block(uint32_t offset);
// Input variables.
double early_termination_threshold_;
double leftness_;
@@ -408,7 +261,7 @@ class ConsStringGenerationData {
double empty_leaf_threshold_;
unsigned max_leaves_;
// Cached data.
- Handle<String> building_blocks_[NUMBER_OF_BUILDING_BLOCKS];
+ Handle<String> building_blocks_[kNumberOfBuildingBlocks];
String* empty_string_;
RandomNumberGenerator rng_;
// Stats.
@@ -419,15 +272,26 @@ class ConsStringGenerationData {
};
-ConsStringGenerationData::ConsStringGenerationData() {
+ConsStringGenerationData::ConsStringGenerationData(bool long_blocks) {
rng_.init();
InitializeBuildingBlocks(
- building_blocks_, NUMBER_OF_BUILDING_BLOCKS, true, &rng_);
+ building_blocks_, kNumberOfBuildingBlocks, long_blocks, &rng_);
empty_string_ = Isolate::Current()->heap()->empty_string();
Reset();
}
+Handle<String> ConsStringGenerationData::block(uint32_t offset) {
+ return building_blocks_[offset % kNumberOfBuildingBlocks ];
+}
+
+
+Handle<String> ConsStringGenerationData::block(int offset) {
+ CHECK_GE(offset, 0);
+ return building_blocks_[offset % kNumberOfBuildingBlocks];
+}
+
+
void ConsStringGenerationData::Reset() {
early_termination_threshold_ = 0.01;
leftness_ = 0.75;
@@ -436,17 +300,19 @@ void ConsStringGenerationData::Reset() {
max_leaves_ = 1000;
stats_.Reset();
early_terminations_ = 0;
+ rng_.init();
}
-void VerifyConsString(ConsString* cons_string, ConsStringStats* stats) {
+void AccumulateStats(ConsString* cons_string, ConsStringStats* stats) {
int left_length = cons_string->first()->length();
int right_length = cons_string->second()->length();
CHECK(cons_string->length() == left_length + right_length);
// Check left side.
- if (cons_string->first()->IsConsString()) {
+ bool left_is_cons = cons_string->first()->IsConsString();
+ if (left_is_cons) {
stats->left_traversals_++;
- VerifyConsString(ConsString::cast(cons_string->first()), stats);
+ AccumulateStats(ConsString::cast(cons_string->first()), stats);
} else {
CHECK_NE(left_length, 0);
stats->leaves_++;
@@ -455,16 +321,29 @@ void VerifyConsString(ConsString* cons_string, ConsStringStats* stats) {
// Check right side.
if (cons_string->second()->IsConsString()) {
stats->right_traversals_++;
- VerifyConsString(ConsString::cast(cons_string->second()), stats);
+ AccumulateStats(ConsString::cast(cons_string->second()), stats);
} else {
- if (right_length == 0) stats->empty_leaves_++;
+ if (right_length == 0) {
+ stats->empty_leaves_++;
+ CHECK(!left_is_cons);
+ }
stats->leaves_++;
stats->chars_ += right_length;
}
}
-void VerifyConsStringWithOperator(
+void AccumulateStats(Handle<String> cons_string, ConsStringStats* stats) {
+ AssertNoAllocation no_alloc;
+ if (cons_string->IsConsString()) {
+ return AccumulateStats(ConsString::cast(*cons_string), stats);
+ }
+ // This string got flattened by gc.
+ stats->chars_ += cons_string->length();
+}
+
+
+void AccumulateStatsWithOperator(
ConsString* cons_string, ConsStringStats* stats) {
// Init op.
ConsStringIteratorOp op;
@@ -506,11 +385,11 @@ void VerifyConsString(Handle<String> root, ConsStringGenerationData* data) {
CHECK((unsigned)root->length() == data->stats_.chars_);
// Recursive verify.
ConsStringStats stats;
- VerifyConsString(ConsString::cast(*root), &stats);
+ AccumulateStats(ConsString::cast(*root), &stats);
stats.VerifyEqual(data->stats_);
// Iteratively verify.
stats.Reset();
- VerifyConsStringWithOperator(ConsString::cast(*root), &stats);
+ AccumulateStatsWithOperator(ConsString::cast(*root), &stats);
// Don't see these. Must copy over.
stats.empty_leaves_ = data->stats_.empty_leaves_;
stats.left_traversals_ = data->stats_.left_traversals_;
@@ -542,23 +421,32 @@ static Handle<String> ConstructRandomString(ConsStringGenerationData* data,
// Generate left string.
Handle<String> left;
if (terminate_left) {
- left = data->building_blocks_[data->rng_.next(NUMBER_OF_BUILDING_BLOCKS)];
+ left = data->block(data->rng_.next());
data->stats_.leaves_++;
data->stats_.chars_ += left->length();
} else {
- left = ConstructRandomString(data, max_recursion - 1);
data->stats_.left_traversals_++;
}
// Generate right string.
Handle<String> right;
if (terminate_right) {
- right = data->building_blocks_[data->rng_.next(NUMBER_OF_BUILDING_BLOCKS)];
+ right = data->block(data->rng_.next());
data->stats_.leaves_++;
data->stats_.chars_ += right->length();
} else {
- right = ConstructRandomString(data, max_recursion - 1);
data->stats_.right_traversals_++;
}
+ // Generate the necessary sub-nodes recursively.
+ if (!terminate_right) {
+ // Need to balance generation fairly.
+ if (!terminate_left && data->rng_.next(0.5)) {
+ left = ConstructRandomString(data, max_recursion - 1);
+ }
+ right = ConstructRandomString(data, max_recursion - 1);
+ }
+ if (!terminate_left && left.is_null()) {
+ left = ConstructRandomString(data, max_recursion - 1);
+ }
// Build the cons string.
Handle<String> root = FACTORY->NewConsString(left, right);
CHECK(root->IsConsString() && !root->IsFlat());
@@ -572,63 +460,169 @@ static Handle<String> ConstructRandomString(ConsStringGenerationData* data,
}
-static const int kCharacterStreamRandomCases = 150;
-static const int kCharacterStreamEdgeCases =
- kCharacterStreamRandomCases + 5;
+static Handle<String> ConstructLeft(
+ ConsStringGenerationData* data,
+ int depth) {
+ Handle<String> answer = FACTORY->NewStringFromAscii(CStrVector(""));
+ data->stats_.leaves_++;
+ for (int i = 0; i < depth; i++) {
+ Handle<String> block = data->block(i);
+ Handle<String> next = FACTORY->NewConsString(answer, block);
+ if (next->IsConsString()) data->stats_.leaves_++;
+ data->stats_.chars_ += block->length();
+ answer = next;
+ }
+ data->stats_.left_traversals_ = data->stats_.leaves_ - 2;
+ return answer;
+}
-static Handle<String> BuildConsStrings(int testCase,
- ConsStringGenerationData* data) {
- // For random constructions, need to reset the generator.
- data->rng_.init();
- for (int j = 0; j < testCase * 50; j++) {
- data->rng_.next();
+static Handle<String> ConstructRight(
+ ConsStringGenerationData* data,
+ int depth) {
+ Handle<String> answer = FACTORY->NewStringFromAscii(CStrVector(""));
+ data->stats_.leaves_++;
+ for (int i = depth - 1; i >= 0; i--) {
+ Handle<String> block = data->block(i);
+ Handle<String> next = FACTORY->NewConsString(block, answer);
+ if (next->IsConsString()) data->stats_.leaves_++;
+ data->stats_.chars_ += block->length();
+ answer = next;
}
- Handle<String> string;
- switch (testCase) {
- case 0:
- return ConstructBalanced(data->building_blocks_);
- case 1:
- return ConstructLeft(data->building_blocks_, DEEP_DEPTH);
- case 2:
- return ConstructRight(data->building_blocks_, DEEP_DEPTH);
- case 3:
- return ConstructLeft(data->building_blocks_, 10);
- case 4:
- return ConstructRight(data->building_blocks_, 10);
- case 5:
- return FACTORY->NewConsString(
- data->building_blocks_[0], data->building_blocks_[1]);
- default:
- if (testCase >= kCharacterStreamEdgeCases) {
- CHECK(false);
- return string;
- }
- // Random test case.
- data->Reset();
- string = ConstructRandomString(data, 200);
- AssertNoAllocation no_alloc;
- VerifyConsString(string, data);
-#ifdef DEBUG
- printf(
- "%s: [%d], %s: [%d], %s: [%d], %s: [%d], %s: [%d], %s: [%d]\n",
- "leaves", data->stats_.leaves_,
- "empty", data->stats_.empty_leaves_,
- "chars", data->stats_.chars_,
- "lefts", data->stats_.left_traversals_,
- "rights", data->stats_.right_traversals_,
- "early_terminations", data->early_terminations_);
-#endif
- return string;
- }
+ data->stats_.right_traversals_ = data->stats_.leaves_ - 2;
+ return answer;
+}
+
+
+static Handle<String> ConstructBalancedHelper(
+ ConsStringGenerationData* data,
+ int from,
+ int to) {
+ CHECK(to > from);
+ if (to - from == 1) {
+ data->stats_.chars_ += data->block(from)->length();
+ return data->block(from);
+ }
+ if (to - from == 2) {
+ data->stats_.chars_ += data->block(from)->length();
+ data->stats_.chars_ += data->block(from+1)->length();
+ return FACTORY->NewConsString(data->block(from), data->block(from+1));
+ }
+ Handle<String> part1 =
+ ConstructBalancedHelper(data, from, from + ((to - from) / 2));
+ Handle<String> part2 =
+ ConstructBalancedHelper(data, from + ((to - from) / 2), to);
+ if (part1->IsConsString()) data->stats_.left_traversals_++;
+ if (part2->IsConsString()) data->stats_.right_traversals_++;
+ return FACTORY->NewConsString(part1, part2);
+}
+
+
+static Handle<String> ConstructBalanced(
+ ConsStringGenerationData* data, int depth = DEEP_DEPTH) {
+ Handle<String> string = ConstructBalancedHelper(data, 0, depth);
+ data->stats_.leaves_ =
+ data->stats_.left_traversals_ + data->stats_.right_traversals_ + 2;
+ return string;
+}
+
+
+static StringInputBuffer buffer;
+static ConsStringIteratorOp cons_string_iterator_op_1;
+static ConsStringIteratorOp cons_string_iterator_op_2;
+
+static void Traverse(Handle<String> s1, Handle<String> s2) {
+ int i = 0;
+ buffer.Reset(*s1);
+ StringCharacterStream character_stream_1(*s1, 0, &cons_string_iterator_op_1);
+ StringCharacterStream character_stream_2(*s2, 0, &cons_string_iterator_op_2);
+ StringInputBuffer buffer2(*s2);
+ while (buffer.has_more()) {
+ CHECK(buffer2.has_more());
+ CHECK(character_stream_1.HasMore());
+ CHECK(character_stream_2.HasMore());
+ uint16_t c = buffer.GetNext();
+ CHECK_EQ(c, buffer2.GetNext());
+ CHECK_EQ(c, character_stream_1.GetNext());
+ CHECK_EQ(c, character_stream_2.GetNext());
+ i++;
+ }
+ CHECK(!character_stream_1.HasMore());
+ CHECK(!character_stream_2.HasMore());
+ CHECK_EQ(s1->length(), i);
+ CHECK_EQ(s2->length(), i);
+}
+
+
+static void TraverseFirst(Handle<String> s1, Handle<String> s2, int chars) {
+ int i = 0;
+ buffer.Reset(*s1);
+ StringInputBuffer buffer2(*s2);
+ StringCharacterStream character_stream_1(*s1, 0, &cons_string_iterator_op_1);
+ StringCharacterStream character_stream_2(*s2, 0, &cons_string_iterator_op_2);
+ while (buffer.has_more() && i < chars) {
+ CHECK(buffer2.has_more());
+ CHECK(character_stream_1.HasMore());
+ CHECK(character_stream_2.HasMore());
+ uint16_t c = buffer.GetNext();
+ CHECK_EQ(c, buffer2.GetNext());
+ CHECK_EQ(c, character_stream_1.GetNext());
+ CHECK_EQ(c, character_stream_2.GetNext());
+ i++;
+ }
+ s1->Get(s1->length() - 1);
+ s2->Get(s2->length() - 1);
+}
+
+
+TEST(Traverse) {
+ printf("TestTraverse\n");
+ InitializeVM();
+ v8::HandleScope scope;
+ ZoneScope zone(Isolate::Current()->runtime_zone(), DELETE_ON_EXIT);
+ ConsStringGenerationData data(false);
+ Handle<String> flat = ConstructBalanced(&data);
+ FlattenString(flat);
+ Handle<String> left_asymmetric = ConstructLeft(&data, DEEP_DEPTH);
+ Handle<String> right_asymmetric = ConstructRight(&data, DEEP_DEPTH);
+ Handle<String> symmetric = ConstructBalanced(&data);
+ printf("1\n");
+ Traverse(flat, symmetric);
+ printf("2\n");
+ Traverse(flat, left_asymmetric);
+ printf("3\n");
+ Traverse(flat, right_asymmetric);
+ printf("4\n");
+ Handle<String> left_deep_asymmetric =
+ ConstructLeft(&data, SUPER_DEEP_DEPTH);
+ Handle<String> right_deep_asymmetric =
+ ConstructRight(&data, SUPER_DEEP_DEPTH);
+ printf("5\n");
+ TraverseFirst(left_asymmetric, left_deep_asymmetric, 1050);
+ printf("6\n");
+ TraverseFirst(left_asymmetric, right_deep_asymmetric, 65536);
+ printf("7\n");
+ FlattenString(left_asymmetric);
+ printf("10\n");
+ Traverse(flat, left_asymmetric);
+ printf("11\n");
+ FlattenString(right_asymmetric);
+ printf("12\n");
+ Traverse(flat, right_asymmetric);
+ printf("14\n");
+ FlattenString(symmetric);
+ printf("15\n");
+ Traverse(flat, symmetric);
+ printf("16\n");
+ FlattenString(left_deep_asymmetric);
+ printf("18\n");
}
static void VerifyCharacterStream(
String* flat_string, String* cons_string) {
// Do not want to test ConString traversal on flat string.
- CHECK(flat_string->IsFlat());
- CHECK(!flat_string->IsConsString());
+ CHECK(flat_string->IsFlat() && !flat_string->IsConsString());
CHECK(cons_string->IsConsString());
// TODO(dcarney) Test stream reset as well.
int length = flat_string->length();
@@ -656,30 +650,233 @@ static void VerifyCharacterStream(
}
-TEST(StringCharacterStreamEdgeCases) {
- printf("TestStringCharacterStreamEdgeCases\n");
+static inline void PrintStats(const ConsStringGenerationData& data) {
+#ifdef DEBUG
+printf(
+ "%s: [%d], %s: [%d], %s: [%d], %s: [%d], %s: [%d], %s: [%d]\n",
+ "leaves", data.stats_.leaves_,
+ "empty", data.stats_.empty_leaves_,
+ "chars", data.stats_.chars_,
+ "lefts", data.stats_.left_traversals_,
+ "rights", data.stats_.right_traversals_,
+ "early_terminations", data.early_terminations_);
+#endif
+}
+
+
+template<typename BuildString>
+void TestStringCharacterStream(BuildString build, int test_cases) {
InitializeVM();
Isolate* isolate = Isolate::Current();
HandleScope outer_scope(isolate);
ZoneScope zone(Isolate::Current()->runtime_zone(), DELETE_ON_EXIT);
- ConsStringGenerationData data;
- for (int i = 0; i < kCharacterStreamEdgeCases; i++) {
+ ConsStringGenerationData data(true);
+ bool last_test_did_gc = false;
+ for (int i = 0; i < test_cases; i++) {
printf("%d\n", i);
- isolate->heap()->CollectAllGarbage(
- Heap::kNoGCFlags, "must not allocate in loop");
- AlwaysAllocateScope always_allocate;
HandleScope inner_scope(isolate);
- Handle<String> cons_string = BuildConsStrings(i, &data);
- Handle<String> flat_string = BuildConsStrings(i, &data);
+ // Build flat version of cons string.
+ Handle<String> flat_string = build(i, &data);
+ ConsStringStats flat_string_stats;
+ AccumulateStats(flat_string, &flat_string_stats);
+ // Flatten string.
FlattenString(flat_string);
+ // Build unflattened version of cons string to test.
+ Handle<String> cons_string = build(i, &data);
+ ConsStringStats cons_string_stats;
+ AccumulateStats(cons_string, &cons_string_stats);
+ // Check if gc changed our data structure.
+ bool broken_by_gc =
+ cons_string_stats.leaves_ != data.stats_.leaves_ ||
+ cons_string_stats.leaves_ != flat_string_stats.leaves_;
+ // If gc altered the data structure, do a full collection and retry test.
+ if (broken_by_gc) {
+ // Bail if test runs twice.
+ if (last_test_did_gc) CHECK(false);
+ printf("forcing gc\n");
+ isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "retry test");
+ // Retry test.
+ last_test_did_gc = true;
+ i--;
+ continue;
+ }
+ last_test_did_gc = false;
AssertNoAllocation no_alloc;
- CHECK(flat_string->IsConsString() && flat_string->IsFlat());
- VerifyCharacterStream(ConsString::cast(*flat_string)->first(),
- *cons_string);
+ PrintStats(data);
+ // Full verify of cons string.
+ cons_string_stats.VerifyEqual(flat_string_stats);
+ cons_string_stats.VerifyEqual(data.stats_);
+ VerifyConsString(cons_string, &data);
+ String* flat_string_ptr =
+ flat_string->IsConsString() ?
+ ConsString::cast(*flat_string)->first() :
+ *flat_string;
+ VerifyCharacterStream(flat_string_ptr, *cons_string);
}
}
+static const int kCharacterStreamNonRandomCases = 8;
+
+
+static Handle<String> BuildEdgeCaseConsString(
+ int test_case, ConsStringGenerationData* data) {
+ data->Reset();
+ switch (test_case) {
+ case 0:
+ return ConstructBalanced(data, 71);
+ case 1:
+ return ConstructLeft(data, 71);
+ case 2:
+ return ConstructRight(data, 71);
+ case 3:
+ return ConstructLeft(data, 10);
+ case 4:
+ return ConstructRight(data, 10);
+ case 5:
+ // 2 element balanced tree.
+ data->stats_.chars_ += data->block(0)->length();
+ data->stats_.chars_ += data->block(1)->length();
+ data->stats_.leaves_ += 2;
+ return FACTORY->NewConsString(data->block(0), data->block(1));
+ case 6:
+ // Simple flattened tree.
+ data->stats_.chars_ += data->block(0)->length();
+ data->stats_.chars_ += data->block(1)->length();
+ data->stats_.leaves_ += 2;
+ data->stats_.empty_leaves_ += 1;
+ {
+ Handle<String> string =
+ FACTORY->NewConsString(data->block(0), data->block(1));
+ FlattenString(string);
+ return string;
+ }
+ case 7:
+ // Left node flattened.
+ data->stats_.chars_ += data->block(0)->length();
+ data->stats_.chars_ += data->block(1)->length();
+ data->stats_.chars_ += data->block(2)->length();
+ data->stats_.leaves_ += 3;
+ data->stats_.empty_leaves_ += 1;
+ data->stats_.left_traversals_ += 1;
+ {
+ Handle<String> left =
+ FACTORY->NewConsString(data->block(0), data->block(1));
+ FlattenString(left);
+ return FACTORY->NewConsString(left, data->block(2));
+ }
+ case 8:
+ // Left node and right node flattened.
+ data->stats_.chars_ += data->block(0)->length();
+ data->stats_.chars_ += data->block(1)->length();
+ data->stats_.chars_ += data->block(2)->length();
+ data->stats_.chars_ += data->block(3)->length();
+ data->stats_.leaves_ += 4;
+ data->stats_.empty_leaves_ += 2;
+ data->stats_.left_traversals_ += 1;
+ data->stats_.right_traversals_ += 1;
+ {
+ Handle<String> left =
+ FACTORY->NewConsString(data->block(0), data->block(1));
+ FlattenString(left);
+ Handle<String> right =
+ FACTORY->NewConsString(data->block(2), data->block(2));
+ FlattenString(right);
+ return FACTORY->NewConsString(left, right);
+ }
+ }
+ UNREACHABLE();
+ return Handle<String>();
+}
+
+
+TEST(StringCharacterStreamEdgeCases) {
+ printf("TestStringCharacterStreamEdgeCases\n");
+ TestStringCharacterStream(
+ BuildEdgeCaseConsString, kCharacterStreamNonRandomCases);
+}
+
+
+static const int kBalances = 3;
+static const int kTreeLengths = 4;
+static const int kEmptyLeaves = 4;
+static const int kUniqueRandomParameters =
+ kBalances*kTreeLengths*kEmptyLeaves;
+
+
+static void InitializeGenerationData(
+ int test_case, ConsStringGenerationData* data) {
+ // Clear the settings and reinit the rng.
+ data->Reset();
+ // Spin up the rng to a known location that is unique per test.
+ static const int kPerTestJump = 501;
+ for (int j = 0; j < test_case*kPerTestJump; j++) {
+ data->rng_.next();
+ }
+ // Choose balanced, left or right heavy trees.
+ switch (test_case % kBalances) {
+ case 0:
+ // Nothing to do. Already balanced.
+ break;
+ case 1:
+ // Left balanced.
+ data->leftness_ = 0.90;
+ data->rightness_ = 0.15;
+ break;
+ case 2:
+ // Right balanced.
+ data->leftness_ = 0.15;
+ data->rightness_ = 0.90;
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ // Must remove the influence of the above decision.
+ test_case /= kBalances;
+ // Choose tree length.
+ switch (test_case % kTreeLengths) {
+ case 0:
+ data->max_leaves_ = 16;
+ data->early_termination_threshold_ = 0.2;
+ break;
+ case 1:
+ data->max_leaves_ = 50;
+ data->early_termination_threshold_ = 0.05;
+ break;
+ case 2:
+ data->max_leaves_ = 500;
+ data->early_termination_threshold_ = 0.03;
+ break;
+ case 3:
+ data->max_leaves_ = 5000;
+ data->early_termination_threshold_ = 0.001;
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ // Must remove the influence of the above decision.
+ test_case /= kTreeLengths;
+ // Choose how much we allow empty nodes, including not at all.
+ data->empty_leaf_threshold_ =
+ 0.03 * static_cast<double>(test_case % kEmptyLeaves);
+}
+
+
+static Handle<String> BuildRandomConsString(
+ int test_case, ConsStringGenerationData* data) {
+ InitializeGenerationData(test_case, data);
+ return ConstructRandomString(data, 200);
+}
+
+
+TEST(StringCharacterStreamRandom) {
Michael Starzinger 2012/12/14 09:23:07 This test is failing on the GC Stress builder. ht
+ printf("StringCharacterStreamRandom\n");
+ TestStringCharacterStream(BuildRandomConsString, kUniqueRandomParameters*7);
+}
+
+
static const int DEEP_ASCII_DEPTH = 100000;
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698