diff options
| author | Federico Igne <federico.igne@cs.ox.ac.uk> | 2020-11-19 23:06:05 +0000 |
|---|---|---|
| committer | Federico Igne <federico.igne@cs.ox.ac.uk> | 2020-11-19 23:06:05 +0000 |
| commit | 343757e71ff21cf92192147c136a8cc615f273b8 (patch) | |
| tree | a08a0093cb09aa72c441bbb2942626dd140cb1a7 /src/test/scala/uk | |
| parent | e84d4a15401b0a83dbb7d502723c33abf656b9ff (diff) | |
| download | RSAComb-343757e71ff21cf92192147c136a8cc615f273b8.tar.gz RSAComb-343757e71ff21cf92192147c136a8cc615f273b8.zip | |
Add wrapper class for (boolean) conjunctive queries
Diffstat (limited to 'src/test/scala/uk')
3 files changed, 297 insertions, 85 deletions
diff --git a/src/test/scala/uk/ac/ox/cs/rsacomb/FilteringProgramSpecs.scala b/src/test/scala/uk/ac/ox/cs/rsacomb/FilteringProgramSpecs.scala index 49abd48..e9a20db 100644 --- a/src/test/scala/uk/ac/ox/cs/rsacomb/FilteringProgramSpecs.scala +++ b/src/test/scala/uk/ac/ox/cs/rsacomb/FilteringProgramSpecs.scala | |||
| @@ -310,89 +310,4 @@ class FilteringProgramSpec | |||
| 310 | 310 | ||
| 311 | import FilteringProgramSpec._ | 311 | import FilteringProgramSpec._ |
| 312 | 312 | ||
| 313 | "Queries" should "have distinct answer and bounded variables" in { | ||
| 314 | for (query <- queries) { | ||
| 315 | val program = new FilteringProgram(query, List()) | ||
| 316 | forAll(program.answer) { v => program.bounded should not contain v } | ||
| 317 | forAll(program.bounded) { v => program.answer should not contain v } | ||
| 318 | } | ||
| 319 | } | ||
| 320 | |||
| 321 | "Query 0" should "have {?obj, ?pred} as bounded variables" in { | ||
| 322 | val pred = Variable.create("obj") | ||
| 323 | val obj = Variable.create("pred") | ||
| 324 | val program = new FilteringProgram(query0, List()) | ||
| 325 | program.bounded should contain theSameElementsAs List(pred, obj) | ||
| 326 | } | ||
| 327 | |||
| 328 | "Query 1" should "have no bounded variable" in { | ||
| 329 | val program = new FilteringProgram(query1, List()) | ||
| 330 | program.bounded shouldBe empty | ||
| 331 | } | ||
| 332 | |||
| 333 | "Query 2" should "have no bounded variable" in { | ||
| 334 | val program = new FilteringProgram(query2, List()) | ||
| 335 | program.bounded shouldBe empty | ||
| 336 | } | ||
| 337 | |||
| 338 | "Query 3" should "have {?w, ?fp} as bounded variables" in { | ||
| 339 | val w = Variable.create("w") | ||
| 340 | val fp = Variable.create("fp") | ||
| 341 | val program = new FilteringProgram(query3, List()) | ||
| 342 | program.bounded should contain theSameElementsAs List(w, fp) | ||
| 343 | } | ||
| 344 | |||
| 345 | "Query 4" should "have no bounded variable" in { | ||
| 346 | val program = new FilteringProgram(query4, List()) | ||
| 347 | program.bounded shouldBe empty | ||
| 348 | } | ||
| 349 | |||
| 350 | "Query 5" should "have a non-empty bounded set" in { | ||
| 351 | val w = Variable.create("w") | ||
| 352 | val c_int = Variable.create("c_int") | ||
| 353 | val f_int = Variable.create("f_int") | ||
| 354 | val c_unit = Variable.create("c_unit") | ||
| 355 | val program = new FilteringProgram(query5, List()) | ||
| 356 | program.bounded should contain theSameElementsAs List( | ||
| 357 | w, | ||
| 358 | c_int, | ||
| 359 | f_int, | ||
| 360 | c_unit | ||
| 361 | ) | ||
| 362 | } | ||
| 363 | |||
| 364 | "Query 6" should "have a non-empty bounded set" in { | ||
| 365 | val w = Variable.create("w") | ||
| 366 | val int = Variable.create("int") | ||
| 367 | val program = new FilteringProgram(query6, List()) | ||
| 368 | program.bounded should contain theSameElementsAs List(w, int) | ||
| 369 | } | ||
| 370 | |||
| 371 | "Query 7" should "have a non-empty bounded set" in { | ||
| 372 | val w = Variable.create("w") | ||
| 373 | val z = Variable.create("z") | ||
| 374 | val u = Variable.create("u") | ||
| 375 | val strat_unit_name = Variable.create("strat_unit_name") | ||
| 376 | val wellbore = Variable.create("wellbore") | ||
| 377 | val cored_int = Variable.create("cored_int") | ||
| 378 | val c = Variable.create("c") | ||
| 379 | val sample_depth = Variable.create("sample_depth") | ||
| 380 | val p = Variable.create("p") | ||
| 381 | val top = Variable.create("top") | ||
| 382 | val bot = Variable.create("bot") | ||
| 383 | val program = new FilteringProgram(query7, List()) | ||
| 384 | program.bounded should contain theSameElementsAs List( | ||
| 385 | w, | ||
| 386 | z, | ||
| 387 | u, | ||
| 388 | strat_unit_name, | ||
| 389 | wellbore, | ||
| 390 | cored_int, | ||
| 391 | c, | ||
| 392 | sample_depth, | ||
| 393 | p, | ||
| 394 | top, | ||
| 395 | bot | ||
| 396 | ) | ||
| 397 | } | ||
| 398 | } | 313 | } |
diff --git a/src/test/scala/uk/ac/ox/cs/rsacomb/sparql/ConjunctiveQueryAnswerSpecs.scala b/src/test/scala/uk/ac/ox/cs/rsacomb/sparql/ConjunctiveQueryAnswerSpecs.scala new file mode 100644 index 0000000..65c3e29 --- /dev/null +++ b/src/test/scala/uk/ac/ox/cs/rsacomb/sparql/ConjunctiveQueryAnswerSpecs.scala | |||
| @@ -0,0 +1,62 @@ | |||
| 1 | package uk.ac.ox.cs.rsacomb.sparql | ||
| 2 | |||
| 3 | import org.scalatest.flatspec.AnyFlatSpec | ||
| 4 | import org.scalatest.matchers.should.Matchers | ||
| 5 | import tech.oxfordsemantic.jrdfox.logic.expression.IRI | ||
| 6 | |||
| 7 | object ConjunctiveQueryAnswerSpec { | ||
| 8 | |||
| 9 | val iri1 = IRI.create("_:iri1") | ||
| 10 | val iri2 = IRI.create("_:iri2") | ||
| 11 | val iri3 = IRI.create("_:iri3") | ||
| 12 | |||
| 13 | val oneAnswer = new ConjunctiveQueryAnswers(false, Seq(Seq(iri1, iri2, iri3))) | ||
| 14 | val multipleAnswers = | ||
| 15 | new ConjunctiveQueryAnswers( | ||
| 16 | false, | ||
| 17 | Seq(Seq(iri1, iri1), Seq(iri1, iri2), Seq(iri1, iri3)) | ||
| 18 | ) | ||
| 19 | val noAnswer = new ConjunctiveQueryAnswers(false, Seq()) | ||
| 20 | val emptyAnswer = new ConjunctiveQueryAnswers(false, Seq(Seq())) | ||
| 21 | |||
| 22 | val falseAnswer = new ConjunctiveQueryAnswers(true, Seq()) | ||
| 23 | val trueAnswer1 = new ConjunctiveQueryAnswers(true, Seq(Seq())) | ||
| 24 | val trueAnswer2 = | ||
| 25 | new ConjunctiveQueryAnswers( | ||
| 26 | true, | ||
| 27 | Seq(Seq(iri1, iri1), Seq(iri1, iri2), Seq(iri1, iri3)) | ||
| 28 | ) | ||
| 29 | } | ||
| 30 | |||
| 31 | class ConjunctiveQueryAnswerSpec extends AnyFlatSpec with Matchers { | ||
| 32 | |||
| 33 | import ConjunctiveQueryAnswerSpec._ | ||
| 34 | |||
| 35 | "A conjunctive query" should "print a single line if it has a single answer" in { | ||
| 36 | oneAnswer.toString shouldBe s"($iri1, $iri2, $iri3)" | ||
| 37 | } | ||
| 38 | |||
| 39 | it should "print multiple answers on multiple lines" in { | ||
| 40 | multipleAnswers.toString shouldBe s"($iri1, $iri1)\n($iri1, $iri2)\n($iri1, $iri3)" | ||
| 41 | } | ||
| 42 | |||
| 43 | it should "print a special \"NO ANSWER\" string when it has no answer" in { | ||
| 44 | noAnswer.toString shouldBe "NO ANSWER" | ||
| 45 | } | ||
| 46 | |||
| 47 | it should "print an empty list when it has an empty answer" in { | ||
| 48 | emptyAnswer.toString shouldBe "()" | ||
| 49 | } | ||
| 50 | |||
| 51 | "A boolean conjunctive query" should "print \"FALSE\" when it has no answer" in { | ||
| 52 | falseAnswer.toString shouldBe "FALSE" | ||
| 53 | } | ||
| 54 | |||
| 55 | it should "print \"TRUE\" when it has a single empty answer" in { | ||
| 56 | trueAnswer1.toString shouldBe "TRUE" | ||
| 57 | } | ||
| 58 | |||
| 59 | it should "print \"TRUE\" when it has a non-empty collection of answers" in { | ||
| 60 | trueAnswer2.toString shouldBe "TRUE" | ||
| 61 | } | ||
| 62 | } | ||
diff --git a/src/test/scala/uk/ac/ox/cs/rsacomb/sparql/ConjunctiveQuerySpec.scala b/src/test/scala/uk/ac/ox/cs/rsacomb/sparql/ConjunctiveQuerySpec.scala new file mode 100644 index 0000000..e683d36 --- /dev/null +++ b/src/test/scala/uk/ac/ox/cs/rsacomb/sparql/ConjunctiveQuerySpec.scala | |||
| @@ -0,0 +1,235 @@ | |||
| 1 | package uk.ac.ox.cs.rsacomb.sparql | ||
| 2 | |||
| 3 | import org.scalatest.{Inspectors, OptionValues} | ||
| 4 | import org.scalatest.flatspec.AnyFlatSpec | ||
| 5 | import org.scalatest.matchers.should.Matchers | ||
| 6 | import tech.oxfordsemantic.jrdfox.logic.expression.Variable | ||
| 7 | |||
| 8 | object ConjunctiveQuerySpec { | ||
| 9 | |||
| 10 | val cq0 = """ | ||
| 11 | PREFIX : <http://example.com/rsa_example.owl#> | ||
| 12 | |||
| 13 | SELECT ?X | ||
| 14 | WHERE { | ||
| 15 | ?X a :D ; | ||
| 16 | :R ?Y . | ||
| 17 | ?Y :S ?Z . | ||
| 18 | ?Z a :D . | ||
| 19 | } | ||
| 20 | """ | ||
| 21 | |||
| 22 | val cq1 = """ | ||
| 23 | PREFIX : <http://example.com/rsa_example.owl#> | ||
| 24 | |||
| 25 | SELECT * | ||
| 26 | WHERE { | ||
| 27 | ?X a :D ; | ||
| 28 | :R ?Y . | ||
| 29 | ?Y :S ?Z . | ||
| 30 | ?Z a :D . | ||
| 31 | } | ||
| 32 | """ | ||
| 33 | |||
| 34 | val cq2 = """ | ||
| 35 | PREFIX : <http://slegger.gitlab.io/slegge-obda/ontology/subsurface-exploration#> | ||
| 36 | SELECT * | ||
| 37 | WHERE { | ||
| 38 | ?w a :Wellbore ; | ||
| 39 | :wellboreDocument ?doc . | ||
| 40 | ?doc :hasURL ?document_hyperlink | ||
| 41 | } | ||
| 42 | """ | ||
| 43 | |||
| 44 | val cq3 = """ | ||
| 45 | PREFIX : <http://slegger.gitlab.io/slegge-obda/ontology/subsurface-exploration#> | ||
| 46 | SELECT ?wellbore ?formation_pressure | ||
| 47 | WHERE { | ||
| 48 | ?w a :Wellbore ; | ||
| 49 | :name ?wellbore ; | ||
| 50 | :hasFormationPressure ?fp . | ||
| 51 | ?fp :valueInStandardUnit ?formation_pressure | ||
| 52 | } | ||
| 53 | """ | ||
| 54 | |||
| 55 | val cq4 = """ | ||
| 56 | PREFIX : <http://slegger.gitlab.io/slegge-obda/ontology/subsurface-exploration#> | ||
| 57 | SELECT * | ||
| 58 | WHERE { | ||
| 59 | ?w a :Wellbore ; | ||
| 60 | :hasGeochemicalMeasurement ?measurement . | ||
| 61 | ?measurement :cgType ?cgtype ; | ||
| 62 | :peakName ?peakType ; | ||
| 63 | :peakHeight ?peak_height ; | ||
| 64 | :peakAmount ?peak_amount | ||
| 65 | } | ||
| 66 | """ | ||
| 67 | |||
| 68 | val cq5 = """ | ||
| 69 | PREFIX : <http://slegger.gitlab.io/slegge-obda/ontology/subsurface-exploration#> | ||
| 70 | SELECT ?wellbore ?unit_name ?discovery | ||
| 71 | WHERE { | ||
| 72 | ?w a :Wellbore ; | ||
| 73 | :name ?wellbore ; | ||
| 74 | :hasWellboreInterval ?c_int ; | ||
| 75 | :hasWellboreInterval ?f_int . | ||
| 76 | ?c_int :hasUnit ?c_unit . | ||
| 77 | ?c_unit :name ?unit_name . | ||
| 78 | ?f_int a :FluidZone ; | ||
| 79 | :name ?discovery ; | ||
| 80 | :overlapsWellboreInterval ?c_int | ||
| 81 | } | ||
| 82 | """ | ||
| 83 | |||
| 84 | val cq6 = """ | ||
| 85 | PREFIX : <http://slegger.gitlab.io/slegge-obda/ontology/subsurface-exploration#> | ||
| 86 | SELECT DISTINCT ?wellbore ?content | ||
| 87 | WHERE { | ||
| 88 | ?w a :Wellbore ; | ||
| 89 | :name ?wellbore ; | ||
| 90 | :hasWellboreInterval ?int . | ||
| 91 | ?int a :FluidZone ; | ||
| 92 | :fluidZoneContent ?content | ||
| 93 | } | ||
| 94 | """ | ||
| 95 | |||
| 96 | val cq7 = """ | ||
| 97 | PREFIX : <http://slegger.gitlab.io/slegge-obda/ontology/subsurface-exploration#> | ||
| 98 | SELECT ?wName ?sample ?porosity ?top_depth_md ?bot_depth_md | ||
| 99 | WHERE { | ||
| 100 | ?w a :Wellbore ; | ||
| 101 | :name ?wName ; | ||
| 102 | :hasWellboreInterval ?z . | ||
| 103 | ?z :hasUnit ?u . | ||
| 104 | ?u :name ?strat_unit_name . | ||
| 105 | ?wellbore :hasWellboreInterval ?cored_int . | ||
| 106 | ?c :extractedFrom ?cored_int ; | ||
| 107 | :hasCoreSample ?sample . | ||
| 108 | ?sample :hasDepth ?sample_depth . | ||
| 109 | ?sample_depth | ||
| 110 | :inWellboreInterval ?z . | ||
| 111 | ?sample :hasPorosity ?p . | ||
| 112 | ?p :valueInStandardUnit ?porosity . | ||
| 113 | ?z :hasTopDepth ?top . | ||
| 114 | ?top a :MeasuredDepth ; | ||
| 115 | :valueInStandardUnit ?top_depth_md . | ||
| 116 | ?z :hasBottomDepth ?bot . | ||
| 117 | ?bot a :MeasuredDepth ; | ||
| 118 | :valueInStandardUnit ?bot_depth_md | ||
| 119 | } | ||
| 120 | """ | ||
| 121 | |||
| 122 | val bcq0 = """ | ||
| 123 | PREFIX : <http://example.com/scrubs/casting/> | ||
| 124 | ASK { | ||
| 125 | :turk a :Doctor ; | ||
| 126 | :married ?X . | ||
| 127 | ?X a :Nurse . | ||
| 128 | } | ||
| 129 | """ | ||
| 130 | |||
| 131 | val queries = | ||
| 132 | List(cq0, cq1, cq2, cq3, cq4, cq5, cq6, cq7, bcq0) | ||
| 133 | |||
| 134 | } | ||
| 135 | |||
| 136 | class ConjunctiveQuerySpec | ||
| 137 | extends AnyFlatSpec | ||
| 138 | with Matchers | ||
| 139 | with Inspectors | ||
| 140 | with OptionValues { | ||
| 141 | |||
| 142 | import ConjunctiveQuerySpec._ | ||
| 143 | |||
| 144 | "A conjunctive query" should "result in a `ConjunctiveQuery` instance" in { | ||
| 145 | ConjunctiveQuery(cq0) shouldBe defined | ||
| 146 | } | ||
| 147 | |||
| 148 | "A boolean conjunctive query" should "result in a `ConjunctiveQuery` instance" in { | ||
| 149 | ConjunctiveQuery(bcq0) shouldBe defined | ||
| 150 | } | ||
| 151 | |||
| 152 | "A query with proper SELECT defined" should "not be a BCQ" in { | ||
| 153 | ConjunctiveQuery(cq0).value should not be 'boolean | ||
| 154 | } | ||
| 155 | |||
| 156 | "A query with a \"*\" SELECT" should "not be a BCQ" in { | ||
| 157 | ConjunctiveQuery(cq1).value should not be 'boolean | ||
| 158 | } | ||
| 159 | |||
| 160 | "An ASK query" should "not be a BCQ" in { | ||
| 161 | ConjunctiveQuery(bcq0).value shouldBe 'boolean | ||
| 162 | } | ||
| 163 | |||
| 164 | "Queries" should "have distinct answer and bounded variables" in { | ||
| 165 | for (q <- queries) { | ||
| 166 | val cq = ConjunctiveQuery(q) | ||
| 167 | forAll(cq.value.answer) { v => cq.value.bounded should not contain v } | ||
| 168 | forAll(cq.value.bounded) { v => cq.value.answer should not contain v } | ||
| 169 | } | ||
| 170 | } | ||
| 171 | |||
| 172 | "CQ0" should "have {?obj, ?pred} as bounded variables" in { | ||
| 173 | ConjunctiveQuery(cq0).value.bounded should contain theSameElementsAs | ||
| 174 | List( | ||
| 175 | Variable.create("Y"), | ||
| 176 | Variable.create("Z") | ||
| 177 | ) | ||
| 178 | } | ||
| 179 | |||
| 180 | "CQ1" should "have no bounded variable" in { | ||
| 181 | ConjunctiveQuery(cq1).value.bounded shouldBe empty | ||
| 182 | } | ||
| 183 | |||
| 184 | "CQ2" should "have no bounded variable" in { | ||
| 185 | ConjunctiveQuery(cq2).value.bounded shouldBe empty | ||
| 186 | } | ||
| 187 | |||
| 188 | "CQ3" should "have {?w, ?fp} as bounded variables" in { | ||
| 189 | ConjunctiveQuery(cq3).value.bounded should contain theSameElementsAs | ||
| 190 | List( | ||
| 191 | Variable.create("w"), | ||
| 192 | Variable.create("fp") | ||
| 193 | ) | ||
| 194 | } | ||
| 195 | |||
| 196 | "CQ4" should "have no bounded variable" in { | ||
| 197 | ConjunctiveQuery(cq4).value.bounded shouldBe empty | ||
| 198 | } | ||
| 199 | |||
| 200 | "CQ5" should "have a non-empty bounded set" in { | ||
| 201 | ConjunctiveQuery(cq5).value.bounded should contain theSameElementsAs | ||
| 202 | List( | ||
| 203 | Variable.create("w"), | ||
| 204 | Variable.create("c_int"), | ||
| 205 | Variable.create("f_int"), | ||
| 206 | Variable.create("c_unit") | ||
| 207 | ) | ||
| 208 | } | ||
| 209 | |||
| 210 | "CQ6" should "have a non-empty bounded set" in { | ||
| 211 | ConjunctiveQuery(cq6).value.bounded should contain theSameElementsAs | ||
| 212 | List( | ||
| 213 | Variable.create("w"), | ||
| 214 | Variable.create("int") | ||
| 215 | ) | ||
| 216 | } | ||
| 217 | |||
| 218 | "CQ7" should "have a non-empty bounded set" in { | ||
| 219 | ConjunctiveQuery(cq7).value.bounded should contain theSameElementsAs | ||
| 220 | List( | ||
| 221 | Variable.create("w"), | ||
| 222 | Variable.create("z"), | ||
| 223 | Variable.create("u"), | ||
| 224 | Variable.create("strat_unit_name"), | ||
| 225 | Variable.create("wellbore"), | ||
| 226 | Variable.create("cored_int"), | ||
| 227 | Variable.create("c"), | ||
| 228 | Variable.create("sample_depth"), | ||
| 229 | Variable.create("p"), | ||
| 230 | Variable.create("top"), | ||
| 231 | Variable.create("bot") | ||
| 232 | ) | ||
| 233 | } | ||
| 234 | |||
| 235 | } | ||
