PageRenderTime 50ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/src/test/scala/com/codecommit/antixml/PathCreatorSpecs.scala

http://github.com/djspiewak/anti-xml
Scala | 193 lines | 124 code | 38 blank | 31 comment | 8 complexity | 0014e3425629ccc84142a0f49755b942 MD5 | raw file
  1. /*
  2. * Copyright (c) 2011, Daniel Spiewak
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without modification,
  6. * are permitted provided that the following conditions are met:
  7. *
  8. * - Redistributions of source code must retain the above copyright notice, this
  9. * list of conditions and the following disclaimer.
  10. * - Redistributions in binary form must reproduce the above copyright notice, this
  11. * list of conditions and the following disclaimer in the documentation and/or
  12. * other materials provided with the distribution.
  13. * - Neither the name of "Anti-XML" nor the names of its contributors may
  14. * be used to endorse or promote products derived from this software without
  15. * specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  18. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  21. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  22. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  24. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  26. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. package com.codecommit.antixml
  29. import org.specs2.mutable._
  30. import com.codecommit.antixml.PathCreator._
  31. import com.codecommit.antixml.Zipper._
  32. import XML._
  33. import scala.math.Ordering
  34. class PathCreatorSpecs extends SpecificationWithJUnit {
  35. def vec[A](t: Traversable[A]) = Vector(t.toSeq:_*)
  36. val s = *
  37. val x0 = fromString("<root0><a0>foo</a0><b0>baz</b0><c0/></root0>")
  38. val a0 = fromString("<a0>foo</a0>"); val b0 = fromString("<b0>baz</b0>"); val c0 = fromString("<c0/>")
  39. val foo0 = Text("foo"); val baz0 = Text("baz")
  40. val x1 = fromString("<root1><a1>foo</a1><b1>baz</b1><c1/></root1>")
  41. val a1 = fromString("<a1>foo</a1>"); val b1 = fromString("<b1>baz</b1>"); val c1 = fromString("<c1/>")
  42. val foo1 = Text("foo"); val baz1 = Text("baz")
  43. val x2 = fromString("<root2><a2>foo</a2><b2>baz</b2><c2/></root2>")
  44. val a2 = fromString("<a2>foo</a2>"); val b2 = fromString("<b2>baz</b2>"); val c2 = fromString("<c2/>")
  45. val foo2 = Text("foo"); val baz2 = Text("baz")
  46. val group = Group(x0, x1, x2)
  47. def ps(pars: (Elem, Int)*) = List(pars.map(_._2): _*) //List(pars.map(ParentLoc.tupled): _*)
  48. def nl(n: Node, l: Int) = l //WithLoc(n, l)
  49. def pv(n: Node, path: Int*) = PathVal(n, ZipperPath(path: _*))
  50. val root = Vector(pv(x0,0), pv(x1, 1), pv(x2, 2))
  51. val directChild = Vector (
  52. pv(a0, 0, 0), pv(b0, 0, 1), pv(c0, 0, 2),
  53. pv(a1, 1, 0), pv(b1, 1, 1), pv(c1, 1, 2),
  54. pv(a2, 2, 0), pv(b2, 2, 1), pv(c2, 2, 2)
  55. )
  56. val rest = Vector (
  57. pv(foo0, 0, 0, 0), pv(baz0, 0, 1, 0),
  58. pv(foo1, 1, 0, 0), pv(baz1, 1, 1, 0),
  59. pv(foo2, 2, 0, 0), pv(baz2, 2, 1, 0)
  60. )
  61. "allMaximalChildren" should {
  62. "stop at the highest match" in {
  63. vec(allMaximalChildren(s)(group)) mustEqual directChild.sortBy(pathKeys)
  64. }
  65. "find deep matches" in {
  66. val sel = Selector({case x:Text => x})
  67. vec(allMaximalChildren(sel)(group)) mustEqual rest.sortBy(pathKeys)
  68. }
  69. "find matches at mixed levels" in {
  70. val sel = Selector({
  71. case e:Elem if e.name == "a0" => e
  72. case t:Text => t
  73. })
  74. vec(allMaximalChildren(sel)(group)) mustEqual (directChild.take(1) ++ rest.drop(1)).sortBy(pathKeys)
  75. }
  76. }
  77. "allMaximal" should {
  78. "stop at the highest match" in {
  79. vec(allMaximal(s)(group)) mustEqual root.sortBy(pathKeys)
  80. }
  81. "find deep matches" in {
  82. val sel = Selector({case x:Text => x})
  83. vec(allMaximal(sel)(group)) mustEqual rest.sortBy(pathKeys)
  84. }
  85. "find matches at mixed levels" in {
  86. val sel = Selector({
  87. case e:Elem if e.name == "a0" => e
  88. case t:Text => t
  89. })
  90. vec(allMaximal(sel)(group)) mustEqual (directChild.take(1) ++ rest.drop(1)).sortBy(pathKeys)
  91. }
  92. "find matches at mixed levels 2" in {
  93. val sel = Selector({
  94. case e:Elem if e.name == "root0" || e.name=="a0" || e.name=="a1" => e
  95. case t:Text => t
  96. })
  97. vec(allMaximal(sel)(group)) mustEqual (root.take(1) ++ directChild.drop(3).take(1) ++ rest.drop(3)).sortBy(pathKeys)
  98. }
  99. }
  100. "Path values" should {
  101. "ignore empty groups" in {
  102. val empty = Group()
  103. vec(fromNodes(s)(empty)) mustEqual Nil
  104. vec(all(s)(empty)) mustEqual Nil
  105. vec(directChildren(s)(empty)) mustEqual Nil
  106. vec(allChildren(s)(empty)) mustEqual Nil
  107. }
  108. "take from the root of the nodes" in {
  109. vec(fromNodes(s)(group)) mustEqual root.sortBy(pathKeys)
  110. }
  111. "take the children of the root nodes" in {
  112. vec(directChildren(s)(group)) mustEqual directChild.sortBy(pathKeys)
  113. }
  114. "take all the nodes recursively, depth first" in {
  115. vec(all(s)(group)) mustEqual (root ++ directChild ++ rest).sortBy(pathKeys)
  116. }
  117. "take all children nodes recursively, depth first" in {
  118. vec(allChildren(s)(group)) mustEqual (directChild ++ rest).sortBy(pathKeys)
  119. }
  120. "apply selectors at the root level" in {
  121. val sel = Selector({ case Elem(_, "root1", _, _, _) => elem("selected") })
  122. vec(fromNodes(sel)(group)) mustEqual Vector(pv(elem("selected"), 1))
  123. }
  124. "apply selectors to the children of the root" in {
  125. val sel = Selector({ case Elem(_, "b2", _, _, _) => elem("selected") })
  126. vec(directChildren(sel)(group)) mustEqual Vector(pv(elem("selected"),2,1))
  127. }
  128. val selDeep = Selector({
  129. case Elem(_, "root2", _, _, _) => elem("selected")
  130. case Elem(_, "c1", _, _, _) => elem("selected")
  131. case Elem(_, "b2", _, _, _) => elem("selected")
  132. case Text("baz") => Text("selected")
  133. })
  134. val selResRoot = Vector(pv(elem("selected"),2))
  135. val selResNoRoot = List(
  136. pv(elem("selected"),1,2),
  137. pv(elem("selected"),2,1),
  138. pv(Text("selected"),0,1,0),
  139. pv(Text("selected"),1,1,0),
  140. pv(Text("selected"),2,1,0)
  141. )
  142. "apply selectors recursively" in {
  143. vec(all(selDeep)(group)) mustEqual (selResRoot ++ selResNoRoot).sortBy(pathKeys)
  144. }
  145. "apply selectors recursively on the children" in {
  146. vec(allChildren(selDeep)(group)) mustEqual selResNoRoot.sortBy(pathKeys)
  147. }
  148. }
  149. def elem(name: String) = Elem(None, name, Attributes(), Map(), Group())
  150. /**
  151. * Returns the indices of the specified PathVal starting at the top. Note that depth-first
  152. * order on PathVals is equivalent to Lexicographic order on their pathKeys.
  153. */
  154. def pathKeys(p: PathVal[_]):Iterable[Int] = p.path
  155. }