js/src/jsapi-tests/testFindSCCs.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 * vim: set ts=8 sts=4 et sw=4 tw=99:
michael@0 3 */
michael@0 4 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 5 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 7
michael@0 8 #include <stdarg.h>
michael@0 9 #include <string.h>
michael@0 10
michael@0 11 #include "gc/FindSCCs.h"
michael@0 12 #include "jsapi-tests/tests.h"
michael@0 13
michael@0 14 static const unsigned MaxVertices = 10;
michael@0 15
michael@0 16 using js::gc::GraphNodeBase;
michael@0 17 using js::gc::ComponentFinder;
michael@0 18
michael@0 19 struct TestNode : public GraphNodeBase<TestNode>
michael@0 20 {
michael@0 21 unsigned index;
michael@0 22 bool hasEdge[MaxVertices];
michael@0 23
michael@0 24 void findOutgoingEdges(ComponentFinder<TestNode> &finder);
michael@0 25 };
michael@0 26
michael@0 27 static TestNode Vertex[MaxVertices];
michael@0 28
michael@0 29 void
michael@0 30 TestNode::findOutgoingEdges(ComponentFinder<TestNode> &finder)
michael@0 31 {
michael@0 32 for (unsigned i = 0; i < MaxVertices; ++i) {
michael@0 33 if (hasEdge[i])
michael@0 34 finder.addEdgeTo(&Vertex[i]);
michael@0 35 }
michael@0 36 }
michael@0 37
michael@0 38 BEGIN_TEST(testFindSCCs)
michael@0 39 {
michael@0 40 // no vertices
michael@0 41
michael@0 42 setup(0);
michael@0 43 run();
michael@0 44 CHECK(end());
michael@0 45
michael@0 46 // no edges
michael@0 47
michael@0 48 setup(1);
michael@0 49 run();
michael@0 50 CHECK(group(0, -1));
michael@0 51 CHECK(end());
michael@0 52
michael@0 53 setup(3);
michael@0 54 run();
michael@0 55 CHECK(group(2, -1));
michael@0 56 CHECK(group(1, -1));
michael@0 57 CHECK(group(0, -1));
michael@0 58 CHECK(end());
michael@0 59
michael@0 60 // linear
michael@0 61
michael@0 62 setup(3);
michael@0 63 edge(0, 1);
michael@0 64 edge(1, 2);
michael@0 65 run();
michael@0 66 CHECK(group(0, -1));
michael@0 67 CHECK(group(1, -1));
michael@0 68 CHECK(group(2, -1));
michael@0 69 CHECK(end());
michael@0 70
michael@0 71 // tree
michael@0 72
michael@0 73 setup(3);
michael@0 74 edge(0, 1);
michael@0 75 edge(0, 2);
michael@0 76 run();
michael@0 77 CHECK(group(0, -1));
michael@0 78 CHECK(group(2, -1));
michael@0 79 CHECK(group(1, -1));
michael@0 80 CHECK(end());
michael@0 81
michael@0 82 // cycles
michael@0 83
michael@0 84 setup(3);
michael@0 85 edge(0, 1);
michael@0 86 edge(1, 2);
michael@0 87 edge(2, 0);
michael@0 88 run();
michael@0 89 CHECK(group(0, 1, 2, -1));
michael@0 90 CHECK(end());
michael@0 91
michael@0 92 setup(4);
michael@0 93 edge(0, 1);
michael@0 94 edge(1, 2);
michael@0 95 edge(2, 1);
michael@0 96 edge(2, 3);
michael@0 97 run();
michael@0 98 CHECK(group(0, -1));
michael@0 99 CHECK(group(1, 2, -1));
michael@0 100 CHECK(group(3, -1));
michael@0 101 CHECK(end());
michael@0 102
michael@0 103 // remaining
michael@0 104
michael@0 105 setup(2);
michael@0 106 edge(0, 1);
michael@0 107 run();
michael@0 108 CHECK(remaining(0, 1, -1));
michael@0 109 CHECK(end());
michael@0 110
michael@0 111 setup(2);
michael@0 112 edge(0, 1);
michael@0 113 run();
michael@0 114 CHECK(group(0, -1));
michael@0 115 CHECK(remaining(1, -1));
michael@0 116 CHECK(end());
michael@0 117
michael@0 118 setup(2);
michael@0 119 edge(0, 1);
michael@0 120 run();
michael@0 121 CHECK(group(0, -1));
michael@0 122 CHECK(group(1, -1));
michael@0 123 CHECK(remaining(-1));
michael@0 124 CHECK(end());
michael@0 125
michael@0 126 return true;
michael@0 127 }
michael@0 128
michael@0 129 unsigned vertex_count;
michael@0 130 ComponentFinder<TestNode> *finder;
michael@0 131 TestNode *resultsList;
michael@0 132
michael@0 133 void setup(unsigned count)
michael@0 134 {
michael@0 135 vertex_count = count;
michael@0 136 for (unsigned i = 0; i < MaxVertices; ++i) {
michael@0 137 TestNode &v = Vertex[i];
michael@0 138 v.gcNextGraphNode = nullptr;
michael@0 139 v.index = i;
michael@0 140 memset(&v.hasEdge, 0, sizeof(v.hasEdge));
michael@0 141 }
michael@0 142 }
michael@0 143
michael@0 144 void edge(unsigned src_index, unsigned dest_index)
michael@0 145 {
michael@0 146 Vertex[src_index].hasEdge[dest_index] = true;
michael@0 147 }
michael@0 148
michael@0 149 void run()
michael@0 150 {
michael@0 151 finder = new ComponentFinder<TestNode>(rt->mainThread.nativeStackLimit[js::StackForSystemCode]);
michael@0 152 for (unsigned i = 0; i < vertex_count; ++i)
michael@0 153 finder->addNode(&Vertex[i]);
michael@0 154 resultsList = finder->getResultsList();
michael@0 155 }
michael@0 156
michael@0 157 bool group(int vertex, ...)
michael@0 158 {
michael@0 159 TestNode *v = resultsList;
michael@0 160
michael@0 161 va_list ap;
michael@0 162 va_start(ap, vertex);
michael@0 163 while (vertex != -1) {
michael@0 164 CHECK(v != nullptr);
michael@0 165 CHECK(v->index == unsigned(vertex));
michael@0 166 v = v->nextNodeInGroup();
michael@0 167 vertex = va_arg(ap, int);
michael@0 168 }
michael@0 169 va_end(ap);
michael@0 170
michael@0 171 CHECK(v == nullptr);
michael@0 172 resultsList = resultsList->nextGroup();
michael@0 173 return true;
michael@0 174 }
michael@0 175
michael@0 176 bool remaining(int vertex, ...)
michael@0 177 {
michael@0 178 TestNode *v = resultsList;
michael@0 179
michael@0 180 va_list ap;
michael@0 181 va_start(ap, vertex);
michael@0 182 while (vertex != -1) {
michael@0 183 CHECK(v != nullptr);
michael@0 184 CHECK(v->index == unsigned(vertex));
michael@0 185 v = (TestNode *)v->gcNextGraphNode;
michael@0 186 vertex = va_arg(ap, int);
michael@0 187 }
michael@0 188 va_end(ap);
michael@0 189
michael@0 190 CHECK(v == nullptr);
michael@0 191 resultsList = nullptr;
michael@0 192 return true;
michael@0 193 }
michael@0 194
michael@0 195 bool end()
michael@0 196 {
michael@0 197 CHECK(resultsList == nullptr);
michael@0 198
michael@0 199 delete finder;
michael@0 200 finder = nullptr;
michael@0 201 return true;
michael@0 202 }
michael@0 203 END_TEST(testFindSCCs)
michael@0 204
michael@0 205 struct TestNode2 : public GraphNodeBase<TestNode2>
michael@0 206 {
michael@0 207 TestNode2 *edge;
michael@0 208
michael@0 209 TestNode2() :
michael@0 210 edge(nullptr)
michael@0 211 {
michael@0 212 }
michael@0 213
michael@0 214 void
michael@0 215 findOutgoingEdges(ComponentFinder<TestNode2> &finder) {
michael@0 216 if (edge)
michael@0 217 finder.addEdgeTo(edge);
michael@0 218 }
michael@0 219 };
michael@0 220
michael@0 221 BEGIN_TEST(testFindSCCsStackLimit)
michael@0 222 {
michael@0 223 /*
michael@0 224 * Test what happens if recusion causes the stack to become full while
michael@0 225 * traversing the graph.
michael@0 226 *
michael@0 227 * The test case is a large number of vertices, almost all of which are
michael@0 228 * arranged in a linear chain. The last few are left unlinked to exercise
michael@0 229 * adding vertices after the stack full condition has already been detected.
michael@0 230 *
michael@0 231 * Such an arrangement with no cycles would normally result in one group for
michael@0 232 * each vertex, but since the stack is exhasted in processing a single group
michael@0 233 * is returned containing all the vertices.
michael@0 234 */
michael@0 235 const unsigned max = 1000000;
michael@0 236 const unsigned initial = 10;
michael@0 237
michael@0 238 TestNode2 *vertices = new TestNode2[max]();
michael@0 239 for (unsigned i = initial; i < (max - 10); ++i)
michael@0 240 vertices[i].edge = &vertices[i + 1];
michael@0 241
michael@0 242 ComponentFinder<TestNode2> finder(rt->mainThread.nativeStackLimit[js::StackForSystemCode]);
michael@0 243 for (unsigned i = 0; i < max; ++i)
michael@0 244 finder.addNode(&vertices[i]);
michael@0 245
michael@0 246 TestNode2 *r = finder.getResultsList();
michael@0 247 CHECK(r);
michael@0 248 TestNode2 *v = r;
michael@0 249
michael@0 250 unsigned count = 0;
michael@0 251 while (v) {
michael@0 252 ++count;
michael@0 253 v = v->nextNodeInGroup();
michael@0 254 }
michael@0 255 CHECK(count == max - initial);
michael@0 256
michael@0 257 count = 0;
michael@0 258 v = r->nextGroup();
michael@0 259 while (v) {
michael@0 260 ++count;
michael@0 261 CHECK(!v->nextNodeInGroup());
michael@0 262 v = v->nextGroup();
michael@0 263 }
michael@0 264
michael@0 265 delete [] vertices;
michael@0 266 return true;
michael@0 267 }
michael@0 268 END_TEST(testFindSCCsStackLimit)

mercurial