github.com/cayleygraph/cayley@v0.7.7/graph/graphtest/integration.go (about) 1 // Copyright 2014 The Cayley Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package graphtest 16 17 import ( 18 "context" 19 "fmt" 20 "os" 21 "path/filepath" 22 "reflect" 23 "sort" 24 "testing" 25 "time" 26 27 "github.com/stretchr/testify/require" 28 29 "github.com/cayleygraph/cayley/graph" 30 "github.com/cayleygraph/cayley/graph/graphtest/testutil" 31 "github.com/cayleygraph/cayley/internal" 32 "github.com/cayleygraph/cayley/query" 33 "github.com/cayleygraph/cayley/query/gizmo" 34 _ "github.com/cayleygraph/cayley/writer" 35 ) 36 37 const ( 38 format = "nquads" 39 timeout = 300 * time.Second 40 ) 41 42 const ( 43 nSpeed = "Speed" 44 nLakeH = "The Lake House" 45 46 SandraB = "Sandra Bullock" 47 KeanuR = "Keanu Reeves" 48 ) 49 50 func checkIntegration(t testing.TB, force bool) { 51 if testing.Short() { 52 t.SkipNow() 53 } 54 if !force && os.Getenv("RUN_INTEGRATION") != "true" { 55 t.Skip("skipping integration tests; set RUN_INTEGRATION=true to run them") 56 } 57 } 58 59 func TestIntegration(t *testing.T, gen testutil.DatabaseFunc, force bool) { 60 checkIntegration(t, force) 61 qs, closer := prepare(t, gen) 62 defer closer() 63 64 checkQueries(t, qs, timeout) 65 } 66 67 func BenchmarkIntegration(t *testing.B, gen testutil.DatabaseFunc, force bool) { 68 checkIntegration(t, force) 69 benchmarkQueries(t, gen) 70 } 71 72 func costarTag(id, c1, c1m, c2, c2m string) map[string]string { 73 return map[string]string{ 74 "id": id, 75 "costar1_actor": c1, 76 "costar1_movie": c1m, 77 "costar2_actor": c2, 78 "costar2_movie": c2m, 79 } 80 } 81 82 var queries = []struct { 83 message string 84 long bool 85 query string 86 tag string 87 // for testing 88 skip bool 89 expect []interface{} 90 }{ 91 // Easy one to get us started. How quick is the most straightforward retrieval? 92 { 93 message: "name predicate", 94 query: ` 95 g.V("Humphrey Bogart").in("<name>").all() 96 `, 97 expect: []interface{}{ 98 map[string]string{"id": "</en/humphrey_bogart>"}, 99 }, 100 }, 101 102 // Grunty queries. 103 // 2014-07-12: This one seems to return in ~20ms in memory; 104 // that's going to be measurably slower for every other backend. 105 { 106 message: "two large sets with no intersection", 107 query: ` 108 function getId(x) { return g.V(x).in("<name>") } 109 var actor_to_film = g.M().in("</film/performance/actor>").in("</film/film/starring>") 110 111 getId("Oliver Hardy").follow(actor_to_film).out("<name>").intersect( 112 getId("Mel Blanc").follow(actor_to_film).out("<name>")).all() 113 `, 114 expect: nil, 115 }, 116 117 // 2014-07-12: This one takes about 4 whole seconds in memory. This is a behemoth. 118 { 119 message: "three huge sets with small intersection", 120 long: true, 121 query: ` 122 function getId(x) { return g.V(x).in("<name>") } 123 var actor_to_film = g.M().in("</film/performance/actor>").in("</film/film/starring>") 124 125 var a = getId("Oliver Hardy").follow(actor_to_film).followR(actor_to_film) 126 var b = getId("Mel Blanc").follow(actor_to_film).followR(actor_to_film) 127 var c = getId("Billy Gilbert").follow(actor_to_film).followR(actor_to_film) 128 129 seen = {} 130 131 a.intersect(b).intersect(c).forEach(function (d) { 132 if (!(d.id in seen)) { 133 seen[d.id] = true; 134 g.emit(d) 135 } 136 }) 137 `, 138 expect: []interface{}{ 139 map[string]string{"id": "</en/sterling_holloway>"}, 140 map[string]string{"id": "</en/billy_gilbert>"}, 141 }, 142 }, 143 144 // This is more of an optimization problem that will get better over time. This takes a lot 145 // of wrong turns on the walk down to what is ultimately the name, but top AND has it easy 146 // as it has a fixed ID. Exercises Contains(). 147 { 148 message: "the helpless checker", 149 long: true, 150 query: ` 151 g.V().as("person").in("<name>").in().in().out("<name>").is("Casablanca").all() 152 `, 153 tag: "person", 154 expect: []interface{}{ 155 map[string]string{"id": "Casablanca", "person": "Ingrid Bergman"}, 156 map[string]string{"id": "Casablanca", "person": "Madeleine LeBeau"}, 157 map[string]string{"id": "Casablanca", "person": "Joy Page"}, 158 map[string]string{"id": "Casablanca", "person": "Claude Rains"}, 159 map[string]string{"id": "Casablanca", "person": "S.Z. Sakall"}, 160 map[string]string{"id": "Casablanca", "person": "Helmut Dantine"}, 161 map[string]string{"id": "Casablanca", "person": "Conrad Veidt"}, 162 map[string]string{"id": "Casablanca", "person": "Paul Henreid"}, 163 map[string]string{"id": "Casablanca", "person": "Peter Lorre"}, 164 map[string]string{"id": "Casablanca", "person": "Sydney Greenstreet"}, 165 map[string]string{"id": "Casablanca", "person": "Leonid Kinskey"}, 166 map[string]string{"id": "Casablanca", "person": "Lou Marcelle"}, 167 map[string]string{"id": "Casablanca", "person": "Dooley Wilson"}, 168 map[string]string{"id": "Casablanca", "person": "John Qualen"}, 169 map[string]string{"id": "Casablanca", "person": "Humphrey Bogart"}, 170 }, 171 }, 172 173 // Exercises Not().Contains(), as above. 174 { 175 message: "the helpless checker, negated (films without Ingrid Bergman)", 176 long: true, 177 query: ` 178 g.V().as("person").in("<name>").in().in().out("<name>").except(g.V("Ingrid Bergman").in("<name>").in().in().out("<name>")).is("Casablanca").all() 179 `, 180 tag: "person", 181 expect: nil, 182 }, 183 { 184 message: "the helpless checker, negated (without actors Ingrid Bergman)", 185 long: true, 186 query: ` 187 g.V().as("person").in("<name>").except(g.V("Ingrid Bergman").in("<name>")).in().in().out("<name>").is("Casablanca").all() 188 `, 189 tag: "person", 190 expect: []interface{}{ 191 map[string]string{"id": "Casablanca", "person": "Madeleine LeBeau"}, 192 map[string]string{"id": "Casablanca", "person": "Joy Page"}, 193 map[string]string{"id": "Casablanca", "person": "Claude Rains"}, 194 map[string]string{"id": "Casablanca", "person": "S.Z. Sakall"}, 195 map[string]string{"id": "Casablanca", "person": "Helmut Dantine"}, 196 map[string]string{"id": "Casablanca", "person": "Conrad Veidt"}, 197 map[string]string{"id": "Casablanca", "person": "Paul Henreid"}, 198 map[string]string{"id": "Casablanca", "person": "Peter Lorre"}, 199 map[string]string{"id": "Casablanca", "person": "Sydney Greenstreet"}, 200 map[string]string{"id": "Casablanca", "person": "Leonid Kinskey"}, 201 map[string]string{"id": "Casablanca", "person": "Lou Marcelle"}, 202 map[string]string{"id": "Casablanca", "person": "Dooley Wilson"}, 203 map[string]string{"id": "Casablanca", "person": "John Qualen"}, 204 map[string]string{"id": "Casablanca", "person": "Humphrey Bogart"}, 205 }, 206 }, 207 208 //Q: Who starred in both "The Net" and "Speed" ? 209 //A: "Sandra Bullock" 210 { 211 message: "Net and Speed", 212 query: common + `m1_actors.intersect(m2_actors).out("<name>").all() 213 `, 214 expect: []interface{}{ 215 map[string]string{"id": SandraB, "movie1": "The Net", "movie2": nSpeed}, 216 }, 217 }, 218 219 //Q: Did "Keanu Reeves" star in "The Net" ? 220 //A: No 221 { 222 message: "Keanu in The Net", 223 query: common + `actor2.intersect(m1_actors).out("<name>").all() 224 `, 225 expect: nil, 226 }, 227 228 //Q: Did "Keanu Reeves" star in "Speed" ? 229 //A: Yes 230 { 231 message: "Keanu in Speed", 232 query: common + `actor2.intersect(m2_actors).out("<name>").all() 233 `, 234 expect: []interface{}{ 235 map[string]string{"id": KeanuR, "movie2": nSpeed}, 236 }, 237 }, 238 239 //Q: Has "Keanu Reeves" co-starred with anyone who starred in "The Net" ? 240 //A: "Keanu Reeves" was in "Speed" and "The Lake House" with "Sandra Bullock", 241 // who was in "The Net" 242 { 243 message: "Keanu with other in The Net", 244 long: true, 245 query: common + `actor2.follow(coStars1).intersect(m1_actors).out("<name>").all() 246 `, 247 expect: []interface{}{ 248 map[string]string{"id": SandraB, "movie1": "The Net", "costar1_movie": nSpeed}, 249 map[string]string{"movie1": "The Net", "costar1_movie": nLakeH, "id": SandraB}, 250 }, 251 }, 252 253 //Q: Do "Keanu Reeves" and "Sandra Bullock" have any commons co-stars? 254 //A: Yes, many. For example: SB starred with "Steve Martin" in "The Prince 255 // of Egypt", and KR starred with Steven Martin in "Parenthood". 256 { 257 message: "Keanu and Bullock with other", 258 long: true, 259 query: common + `actor1.save("<name>","costar1_actor").follow(coStars1).intersect(actor2.save("<name>","costar2_actor").follow(coStars2)).out("<name>").all() 260 `, 261 expect: []interface{}{ 262 costarTag(SandraB, SandraB, "The Proposal", KeanuR, nSpeed), 263 costarTag(SandraB, SandraB, "The Proposal", KeanuR, nLakeH), 264 costarTag("Mary Steenburgen", SandraB, "The Proposal", KeanuR, "Parenthood"), 265 costarTag("Craig T. Nelson", SandraB, "The Proposal", KeanuR, "The Devil's Advocate"), 266 costarTag(SandraB, SandraB, "Crash", KeanuR, nSpeed), 267 costarTag(SandraB, SandraB, "Crash", KeanuR, nLakeH), 268 costarTag(SandraB, SandraB, "Gun Shy", KeanuR, nSpeed), 269 costarTag(SandraB, SandraB, "Gun Shy", KeanuR, nLakeH), 270 costarTag(SandraB, SandraB, "Demolition Man", KeanuR, nSpeed), 271 costarTag(SandraB, SandraB, "Demolition Man", KeanuR, nLakeH), 272 costarTag("Benjamin Bratt", SandraB, "Demolition Man", KeanuR, "Thumbsucker"), 273 costarTag(SandraB, SandraB, "Divine Secrets of the Ya-Ya Sisterhood", KeanuR, nSpeed), 274 costarTag(SandraB, SandraB, "Divine Secrets of the Ya-Ya Sisterhood", KeanuR, nLakeH), 275 costarTag("Shirley Knight", SandraB, "Divine Secrets of the Ya-Ya Sisterhood", KeanuR, "The Private Lives of Pippa Lee"), 276 costarTag(SandraB, SandraB, "A Time to Kill", KeanuR, nSpeed), 277 costarTag(SandraB, SandraB, "A Time to Kill", KeanuR, nLakeH), 278 costarTag(SandraB, SandraB, "Forces of Nature", KeanuR, nSpeed), 279 costarTag(SandraB, SandraB, "Forces of Nature", KeanuR, nLakeH), 280 costarTag(SandraB, SandraB, "Hope Floats", KeanuR, nSpeed), 281 costarTag(SandraB, SandraB, "Hope Floats", KeanuR, nLakeH), 282 costarTag(SandraB, SandraB, "Infamous", KeanuR, nSpeed), 283 costarTag(SandraB, SandraB, "Infamous", KeanuR, nLakeH), 284 costarTag("Jeff Daniels", SandraB, "Infamous", KeanuR, nSpeed), 285 costarTag(SandraB, SandraB, "Love Potion No. 9", KeanuR, nSpeed), 286 costarTag(SandraB, SandraB, "Love Potion No. 9", KeanuR, nLakeH), 287 costarTag(SandraB, SandraB, "Miss Congeniality", KeanuR, nSpeed), 288 costarTag(SandraB, SandraB, "Miss Congeniality", KeanuR, nLakeH), 289 costarTag("Benjamin Bratt", SandraB, "Miss Congeniality", KeanuR, "Thumbsucker"), 290 costarTag(SandraB, SandraB, "Miss Congeniality 2: Armed and Fabulous", KeanuR, nSpeed), 291 costarTag(SandraB, SandraB, "Miss Congeniality 2: Armed and Fabulous", KeanuR, nLakeH), 292 costarTag(SandraB, SandraB, "Murder by Numbers", KeanuR, nSpeed), 293 costarTag(SandraB, SandraB, "Murder by Numbers", KeanuR, nLakeH), 294 costarTag(SandraB, SandraB, "Practical Magic", KeanuR, nSpeed), 295 costarTag(SandraB, SandraB, "Practical Magic", KeanuR, nLakeH), 296 costarTag("Dianne Wiest", SandraB, "Practical Magic", KeanuR, "Parenthood"), 297 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "Flying"), 298 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "The Animatrix"), 299 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "Tune in Tomorrow"), 300 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "The Last Time I Committed Suicide"), 301 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "Constantine"), 302 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "Permanent Record"), 303 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "Dangerous Liaisons"), 304 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "The Private Lives of Pippa Lee"), 305 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "A Scanner Darkly"), 306 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "A Walk in the Clouds"), 307 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "Hardball"), 308 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "Life Under Water"), 309 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "Much Ado About Nothing"), 310 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "My Own Private Idaho"), 311 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "Parenthood"), 312 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "Point Break"), 313 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "Providence"), 314 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "River's Edge"), 315 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "Something's Gotta Give"), 316 costarTag(KeanuR, SandraB, nSpeed, KeanuR, nSpeed), 317 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "Sweet November"), 318 costarTag(KeanuR, SandraB, nSpeed, KeanuR, nLakeH), 319 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "The Matrix Reloaded"), 320 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "The Matrix Revisited"), 321 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "The Prince of Pennsylvania"), 322 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "The Replacements"), 323 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "Even Cowgirls Get the Blues"), 324 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "Youngblood"), 325 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "Bill & Ted's Bogus Journey"), 326 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "Bill & Ted's Excellent Adventure"), 327 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "Johnny Mnemonic"), 328 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "The Devil's Advocate"), 329 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "Thumbsucker"), 330 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "I Love You to Death"), 331 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "Bram Stoker's Dracula"), 332 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "The Gift"), 333 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "Little Buddha"), 334 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "The Night Watchman"), 335 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "Chain Reaction"), 336 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "Babes in Toyland"), 337 costarTag(KeanuR, SandraB, nSpeed, KeanuR, "The Day the Earth Stood Still"), 338 costarTag(SandraB, SandraB, nSpeed, KeanuR, nSpeed), 339 costarTag(SandraB, SandraB, nSpeed, KeanuR, nLakeH), 340 costarTag("Dennis Hopper", SandraB, nSpeed, KeanuR, "River's Edge"), 341 costarTag("Dennis Hopper", SandraB, nSpeed, KeanuR, nSpeed), 342 costarTag("Jeff Daniels", SandraB, nSpeed, KeanuR, nSpeed), 343 costarTag("Joe Morton", SandraB, nSpeed, KeanuR, nSpeed), 344 costarTag("Alan Ruck", SandraB, nSpeed, KeanuR, nSpeed), 345 costarTag("Glenn Plummer", SandraB, nSpeed, KeanuR, nSpeed), 346 costarTag("Carlos Carrasco", SandraB, nSpeed, KeanuR, nSpeed), 347 costarTag("Beth Grant", SandraB, nSpeed, KeanuR, nSpeed), 348 costarTag("Richard Lineback", SandraB, nSpeed, KeanuR, nSpeed), 349 costarTag("Hawthorne James", SandraB, nSpeed, KeanuR, nSpeed), 350 costarTag("Jordan Lund", SandraB, nSpeed, KeanuR, nSpeed), 351 costarTag("Thomas Rosales, Jr.", SandraB, nSpeed, KeanuR, nSpeed), 352 costarTag(SandraB, SandraB, "Speed 2: Cruise Control", KeanuR, nSpeed), 353 costarTag(SandraB, SandraB, "Speed 2: Cruise Control", KeanuR, nLakeH), 354 costarTag("Glenn Plummer", SandraB, "Speed 2: Cruise Control", KeanuR, nSpeed), 355 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "Flying"), 356 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "The Animatrix"), 357 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "Tune in Tomorrow"), 358 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "The Last Time I Committed Suicide"), 359 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "Constantine"), 360 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "Permanent Record"), 361 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "Dangerous Liaisons"), 362 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "The Private Lives of Pippa Lee"), 363 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "A Scanner Darkly"), 364 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "A Walk in the Clouds"), 365 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "Hardball"), 366 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "Life Under Water"), 367 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "Much Ado About Nothing"), 368 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "My Own Private Idaho"), 369 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "Parenthood"), 370 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "Point Break"), 371 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "Providence"), 372 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "River's Edge"), 373 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "Something's Gotta Give"), 374 costarTag(KeanuR, SandraB, nLakeH, KeanuR, nSpeed), 375 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "Sweet November"), 376 costarTag(KeanuR, SandraB, nLakeH, KeanuR, nLakeH), 377 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "The Matrix Reloaded"), 378 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "The Matrix Revisited"), 379 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "The Prince of Pennsylvania"), 380 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "The Replacements"), 381 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "Even Cowgirls Get the Blues"), 382 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "Youngblood"), 383 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "Bill & Ted's Bogus Journey"), 384 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "Bill & Ted's Excellent Adventure"), 385 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "Johnny Mnemonic"), 386 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "The Devil's Advocate"), 387 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "Thumbsucker"), 388 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "I Love You to Death"), 389 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "Bram Stoker's Dracula"), 390 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "The Gift"), 391 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "Little Buddha"), 392 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "The Night Watchman"), 393 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "Chain Reaction"), 394 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "Babes in Toyland"), 395 costarTag(KeanuR, SandraB, nLakeH, KeanuR, "The Day the Earth Stood Still"), 396 costarTag(SandraB, SandraB, nLakeH, KeanuR, nSpeed), 397 costarTag(SandraB, SandraB, nLakeH, KeanuR, nLakeH), 398 costarTag("Christopher Plummer", SandraB, nLakeH, KeanuR, nLakeH), 399 costarTag("Dylan Walsh", SandraB, nLakeH, KeanuR, nLakeH), 400 costarTag("Shohreh Aghdashloo", SandraB, nLakeH, KeanuR, nLakeH), 401 costarTag("Lynn Collins", SandraB, nLakeH, KeanuR, nLakeH), 402 costarTag(SandraB, SandraB, "The Net", KeanuR, nSpeed), 403 costarTag(SandraB, SandraB, "The Net", KeanuR, nLakeH), 404 costarTag("Michelle Pfeiffer", SandraB, "The Prince of Egypt", KeanuR, "Dangerous Liaisons"), 405 costarTag(SandraB, SandraB, "The Prince of Egypt", KeanuR, nSpeed), 406 costarTag(SandraB, SandraB, "The Prince of Egypt", KeanuR, nLakeH), 407 costarTag("Steve Martin", SandraB, "The Prince of Egypt", KeanuR, "Parenthood"), 408 costarTag(SandraB, SandraB, "Two Weeks Notice", KeanuR, nSpeed), 409 costarTag(SandraB, SandraB, "Two Weeks Notice", KeanuR, nLakeH), 410 costarTag(SandraB, SandraB, "While You Were Sleeping", KeanuR, nSpeed), 411 costarTag(SandraB, SandraB, "While You Were Sleeping", KeanuR, nLakeH), 412 costarTag("Jack Warden", SandraB, "While You Were Sleeping", KeanuR, "The Replacements"), 413 costarTag(SandraB, SandraB, "28 Days", KeanuR, nSpeed), 414 costarTag(SandraB, SandraB, "28 Days", KeanuR, nLakeH), 415 costarTag(SandraB, SandraB, "Premonition", KeanuR, nSpeed), 416 costarTag(SandraB, SandraB, "Premonition", KeanuR, nLakeH), 417 costarTag("Peter Stormare", SandraB, "Premonition", KeanuR, "Constantine"), 418 costarTag(SandraB, SandraB, "Wrestling Ernest Hemingway", KeanuR, nSpeed), 419 costarTag(SandraB, SandraB, "Wrestling Ernest Hemingway", KeanuR, nLakeH), 420 costarTag(SandraB, SandraB, "Fire on the Amazon", KeanuR, nSpeed), 421 costarTag(SandraB, SandraB, "Fire on the Amazon", KeanuR, nLakeH), 422 costarTag("River Phoenix", SandraB, "The Thing Called Love", KeanuR, "My Own Private Idaho"), 423 costarTag("River Phoenix", SandraB, "The Thing Called Love", KeanuR, "I Love You to Death"), 424 costarTag(SandraB, SandraB, "The Thing Called Love", KeanuR, nSpeed), 425 costarTag(SandraB, SandraB, "The Thing Called Love", KeanuR, nLakeH), 426 costarTag(SandraB, SandraB, "In Love and War", KeanuR, nSpeed), 427 costarTag(SandraB, SandraB, "In Love and War", KeanuR, nLakeH), 428 }, 429 }, 430 { 431 message: "Save a number of predicates around a set of nodes", 432 query: ` 433 g.V("_:9037", "_:49278", "_:44112", "_:44709", "_:43382").save("</film/performance/character>", "char").save("</film/performance/actor>", "act").saveR("</film/film/starring>", "film").all() 434 `, 435 expect: []interface{}{ 436 map[string]string{"act": "</en/humphrey_bogart>", "char": "Rick Blaine", "film": "</en/casablanca_1942>", "id": "_:9037"}, 437 map[string]string{"act": "</en/humphrey_bogart>", "char": "Sam Spade", "film": "</en/the_maltese_falcon_1941>", "id": "_:49278"}, 438 map[string]string{"act": "</en/humphrey_bogart>", "char": "Philip Marlowe", "film": "</en/the_big_sleep_1946>", "id": "_:44112"}, 439 map[string]string{"act": "</en/humphrey_bogart>", "char": "Captain Queeg", "film": "</en/the_caine_mutiny_1954>", "id": "_:44709"}, 440 map[string]string{"act": "</en/humphrey_bogart>", "char": "Charlie Allnut", "film": "</en/the_african_queen>", "id": "_:43382"}, 441 }, 442 }, 443 } 444 445 const common = ` 446 var movie1 = g.V().has("<name>", "The Net") 447 var movie2 = g.V().has("<name>", "Speed") 448 var actor1 = g.V().has("<name>", "Sandra Bullock") 449 var actor2 = g.V().has("<name>", "Keanu Reeves") 450 451 // (film) -> starring -> (actor) 452 var filmToActor = g.Morphism().out("</film/film/starring>").out("</film/performance/actor>") 453 454 // (actor) -> starring -> [film -> starring -> (actor)] 455 var coStars1 = g.Morphism().in("</film/performance/actor>").in("</film/film/starring>").save("<name>","costar1_movie").follow(filmToActor) 456 var coStars2 = g.Morphism().in("</film/performance/actor>").in("</film/film/starring>").save("<name>","costar2_movie").follow(filmToActor) 457 458 // Stars for the movies "The Net" and "Speed" 459 var m1_actors = movie1.save("<name>","movie1").follow(filmToActor) 460 var m2_actors = movie2.save("<name>","movie2").follow(filmToActor) 461 ` 462 463 func prepare(t testing.TB, gen testutil.DatabaseFunc) (graph.QuadStore, func()) { 464 qs, _, closer := gen(t) 465 466 const needsLoad = true // TODO: support local setup 467 if needsLoad { 468 qw, err := qs.NewQuadWriter() 469 if err != nil { 470 closer() 471 require.NoError(t, err) 472 } 473 474 start := time.Now() 475 for _, p := range []string{"./", "../"} { 476 err = internal.Load(qw, 0, filepath.Join(p, "../../data/30kmoviedata.nq.gz"), format) 477 if err == nil || !os.IsNotExist(err) { 478 break 479 } 480 } 481 if err != nil { 482 qw.Close() 483 closer() 484 require.NoError(t, err) 485 } 486 err = qw.Close() 487 if err != nil { 488 closer() 489 require.NoError(t, err) 490 } 491 t.Logf("loaded data in %v", time.Since(start)) 492 } 493 return qs, closer 494 } 495 496 func checkQueries(t *testing.T, qs graph.QuadStore, timeout time.Duration) { 497 if qs == nil { 498 t.Fatal("not initialized") 499 } 500 for _, test := range queries { 501 t.Run(test.message, func(t *testing.T) { 502 if testing.Short() && test.long { 503 t.SkipNow() 504 } 505 if test.skip { 506 t.SkipNow() 507 } 508 start := time.Now() 509 ses := gizmo.NewSession(qs) 510 ctx := context.Background() 511 if timeout > 0 { 512 var cancel func() 513 ctx, cancel = context.WithTimeout(ctx, timeout) 514 defer cancel() 515 } 516 it, err := ses.Execute(ctx, test.query, query.Options{ 517 Collation: query.JSON, 518 }) 519 if err != nil { 520 t.Fatal(err) 521 } 522 defer it.Close() 523 var got []interface{} 524 for it.Next(ctx) { 525 got = append(got, it.Result()) 526 } 527 t.Logf("%12v %v", time.Since(start), test.message) 528 529 if len(got) != len(test.expect) { 530 t.Errorf("Unexpected number of results, got:%d expect:%d on %s.", len(got), len(test.expect), test.message) 531 return 532 } 533 if unsortedEqual(got, test.expect) { 534 return 535 } 536 t.Errorf("Unexpected results for %s:\n", test.message) 537 for i := range got { 538 t.Errorf("\n\tgot:%#v\n\texpect:%#v\n", got[i], test.expect[i]) 539 } 540 }) 541 } 542 } 543 544 func unsortedEqual(got, expect []interface{}) bool { 545 gotList := convertToStringList(got) 546 expectList := convertToStringList(expect) 547 return reflect.DeepEqual(gotList, expectList) 548 } 549 550 func convertToStringList(in []interface{}) []string { 551 var out []string 552 for _, x := range in { 553 if xc, ok := x.(map[string]string); ok { 554 for k, v := range xc { 555 out = append(out, fmt.Sprint(k, ":", v)) 556 } 557 } else { 558 for k, v := range x.(map[string]interface{}) { 559 out = append(out, fmt.Sprint(k, ":", v)) 560 } 561 } 562 } 563 sort.Strings(out) 564 return out 565 } 566 567 func benchmarkQueries(b *testing.B, gen testutil.DatabaseFunc) { 568 qs, closer := prepare(b, gen) 569 defer closer() 570 571 for _, bench := range queries { 572 b.Run(bench.message, func(b *testing.B) { 573 if testing.Short() && bench.long { 574 b.Skip() 575 } 576 b.StopTimer() 577 b.ResetTimer() 578 for i := 0; i < b.N; i++ { 579 func() { 580 ctx := context.Background() 581 if timeout > 0 { 582 var cancel func() 583 ctx, cancel = context.WithTimeout(ctx, timeout) 584 defer cancel() 585 } 586 ses := gizmo.NewSession(qs) 587 b.StartTimer() 588 it, err := ses.Execute(ctx, bench.query, query.Options{ 589 Collation: query.Raw, 590 }) 591 if err != nil { 592 b.Fatal(err) 593 } 594 defer it.Close() 595 n := 0 596 for it.Next(ctx) { 597 n++ 598 } 599 if err = it.Err(); err != nil { 600 b.Fatal(err) 601 } 602 b.StopTimer() 603 if n != len(bench.expect) { 604 b.Fatalf("unexpected number of results: %d vs %d", n, len(bench.expect)) 605 } 606 }() 607 } 608 }) 609 } 610 }