diff --git a/src/main/scala/fakeps/fakeps.scala b/src/main/scala/fakeps/fakeps.scala index 9d01584..fab85dd 100644 --- a/src/main/scala/fakeps/fakeps.scala +++ b/src/main/scala/fakeps/fakeps.scala @@ -14,29 +14,23 @@ package object fakeps: * using an immutable map. Unacceptably slow * because of a bug in Map.+(vararg). */ - def fakePsFoldSlow(n: Int): Iterator[(Int, Int)] = reverseEdges { + def fakePsFoldSlow(n: Int): Iterator[(Int, Int)] = reverseEdges: require { n > 0 } - (2 to n).foldLeft { - Map(0 -> Seq(1), 1 -> Seq.empty) - } { (ps, nextPid) => - val randomPid = 1 + Random.nextInt(nextPid - 1) - ps + (randomPid -> (nextPid +: ps(randomPid))) + (nextPid -> Seq.empty) - } - } + (2 to n).foldLeft(Map(0 -> Seq(1), 1 -> Seq.empty)): + (ps, nextPid) => + val randomPid = 1 + Random.nextInt(nextPid - 1) + ps + (randomPid -> (nextPid +: ps(randomPid))) + (nextPid -> Seq.empty) /** * Generates a barebones process tree (ppid -> pid*) of size n * using an immutable map. */ - def fakePsFold(n: Int): Iterator[(Int, Int)] = reverseEdges { + def fakePsFold(n: Int): Iterator[(Int, Int)] = reverseEdges: require { n > 0 } - (2 to n).foldLeft { - Map(0 -> Seq(1), 1 -> Seq.empty) - } { (ps, nextPid) => - val randomPid = 1 + Random.nextInt(nextPid - 1) - ps + (randomPid -> (nextPid +: ps(randomPid))) + (nextPid -> Seq.empty) - } - } + (2 to n).foldLeft(Map(0 -> Seq(1), 1 -> Seq.empty)): + (ps, nextPid) => + val randomPid = 1 + Random.nextInt(nextPid - 1) + ps + (randomPid -> (nextPid +: ps(randomPid))) + (nextPid -> Seq.empty) /** * Generates a barebones process tree (ppid -> pid*) of size n @@ -46,27 +40,26 @@ package object fakeps: require { n > 0 } val ps0 = Vector.fill(n + 1)(Vector.empty[Int]) val ps1 = ps0.updated(0, Vector(1)) - val ps = (2 to n).foldLeft(ps1) { (ps, nextPid) => - val randomPid = 1 + Random.nextInt(nextPid - 1) - ps.updated(randomPid, ps(randomPid) :+ nextPid) - } + val ps = (2 to n).foldLeft(ps1): + (ps, nextPid) => + val randomPid = 1 + Random.nextInt(nextPid - 1) + ps.updated(randomPid, ps(randomPid) :+ nextPid) for ppid <- ps.indices.iterator; pid <- ps(ppid).iterator yield (pid, ppid) /** * Generates a barebones process tree (ppid -> pid*) of size n * using a mutable map. */ - def fakePsMutable(n: Int): Iterator[(Int, Int)] = reverseEdges { + def fakePsMutable(n: Int): Iterator[(Int, Int)] = reverseEdges: require { n > 0 } import scala.collection.mutable.Map val ps = Map(0 -> ArrayBuffer(1), 1 -> ArrayBuffer.empty[Int]) - (2 to n) foreach { nextPid => - val randomPid = 1 + Random.nextInt(nextPid - 1) - ps(nextPid) = ArrayBuffer.empty - ps(randomPid) += nextPid - } + (2 to n).foreach: + nextPid => + val randomPid = 1 + Random.nextInt(nextPid - 1) + ps(nextPid) = ArrayBuffer.empty + ps(randomPid) += nextPid ps.toMap - } /** * Generates a barebones process tree (ppid -> pid*) of size n @@ -76,10 +69,10 @@ package object fakeps: require { n > 0 } val ps = Vector.fill(n + 1)(ArrayBuffer.empty[Int]) ps(0) += 1 - (2 to n) foreach { nextPid => - val randomPid = 1 + Random.nextInt(nextPid - 1) - ps(randomPid) += nextPid - } + (2 to n).foreach: + nextPid => + val randomPid = 1 + Random.nextInt(nextPid - 1) + ps(randomPid) += nextPid for ppid <- ps.indices.iterator; pid <- ps(ppid).iterator yield (pid, ppid) /** @@ -113,10 +106,10 @@ package object fakeps: import scala.jdk.CollectionConverters._ val ps = Vector.fill(n + 1)(new ConcurrentLinkedQueue[Int]) ps(0) add 1 - new ParRange(2 to n) foreach { nextPid => - val randomPid = 1 + Random.nextInt(nextPid - 1) - ps(randomPid) add nextPid - } + new ParRange(2 to n) foreach: + nextPid => + val randomPid = 1 + Random.nextInt(nextPid - 1) + ps(randomPid) add nextPid for ppid <- ps.indices.iterator; pid <- ps(ppid).iterator.nn.asScala yield (pid, ppid) /** @@ -129,10 +122,10 @@ package object fakeps: import scala.collection.concurrent.TrieMap val ps = Vector.fill(n + 1)(TrieMap.empty[Int, Unit]) ps(0) += (1 -> (())) - new ParRange(2 to n) foreach { nextPid => - val randomPid = 1 + Random.nextInt(nextPid - 1) - ps(randomPid) += (nextPid -> (())) - } + new ParRange(2 to n) foreach: + nextPid => + val randomPid = 1 + Random.nextInt(nextPid - 1) + ps(randomPid) += (nextPid -> (())) for ppid <- ps.indices.iterator; (pid, _) <- ps(ppid).iterator yield (pid, ppid) /** diff --git a/src/main/scala/fold/Main.scala b/src/main/scala/fold/Main.scala index 8328732..13b15f7 100644 --- a/src/main/scala/fold/Main.scala +++ b/src/main/scala/fold/Main.scala @@ -13,9 +13,10 @@ object Main extends common.Main with FoldTreeBuilder */ trait FoldTreeBuilder extends common.TreeBuilder: override def buildTree(processes: Iterator[Process]): ProcessTree = - processes.foldLeft(Map.empty: ProcessTree) { (m, p) => - val ppid = p._2 - val children = m.getOrElse(ppid, Vector.empty) :+ p - m + (ppid -> children) - } + processes.foldLeft(Map.empty: ProcessTree): + (m, p) => + val ppid = p._2 + val children = m.getOrElse(ppid, Vector.empty) :+ p + m + (ppid -> children) + end FoldTreeBuilder diff --git a/src/test/scala/common/ParseLineSpec.scala b/src/test/scala/common/ParseLineSpec.scala index 86e52f1..0ae2993 100644 --- a/src/test/scala/common/ParseLineSpec.scala +++ b/src/test/scala/common/ParseLineSpec.scala @@ -6,100 +6,69 @@ import org.scalatest.wordspec.AnyWordSpec /** Tests for the `parseLine` method. */ class ParseLineSpec extends AnyWordSpec with IO: - "The line parser" when { - "given an empty header" should { - "reject this argument" in { - intercept[IllegalArgumentException] { + "The line parser" when: + "given an empty header" should: + "reject this argument" in: + intercept[IllegalArgumentException]: parseLine("") - } - } - } - "given a header without PID" should { - "reject this argument" in { - intercept[IllegalArgumentException] { + "given a header without PID" should: + "reject this argument" in: + intercept[IllegalArgumentException]: parseLine("PPID CMD") - } - } - } - "given a header without PPID" should { - "reject this argument" in { - intercept[IllegalArgumentException] { + "given a header without PPID" should: + "reject this argument" in: + intercept[IllegalArgumentException]: parseLine("PID CMD") - } - } - } - "given a header without CMD" should { - "reject this argument" in { - intercept[IllegalArgumentException] { + "given a header without CMD" should: + "reject this argument" in: + intercept[IllegalArgumentException]: parseLine("PPID PID") - } - } - } - "given an simple header" should { + "given an simple header" should: val parser = parseLine("PPID PID CMD") - "reject an empty line" in { - intercept[RuntimeException] { + "reject an empty line" in: + intercept[RuntimeException]: parser("") - } - } - "reject an invalid line" in { - intercept[RuntimeException] { + "reject an invalid line" in: + intercept[RuntimeException]: parser("") - } - } - "parse a valid line" in { + "parse a valid line" in: // PPID PID CMD assert(parser("1 2 asdf") == (2, 1, "asdf")) - } - } - "given an complex header" should { + "given an complex header" should: val parser = parseLine("i1 PPID i2 PID i3 CMD") - "reject an empty line" in { - intercept[RuntimeException] { + "reject an empty line" in: + intercept[RuntimeException]: parser("") - } - } - "reject an invalid line" in { - intercept[RuntimeException] { + "reject an invalid line" in: + intercept[RuntimeException]: parser("") - } - } - "parse a valid line" in { + "parse a valid line" in: // i1 PPID i2 PID i3 CMD assert(parser("i1 1 i2 2 i3 asdf") == (2, 1, "asdf")) - } - } - "given an actual header" should { + "given an actual header" should: val parser = parseLine(" UID PID PPID C STIME TTY TIME CMD") - "reject an empty line" in { - intercept[RuntimeException] { + "reject an empty line" in: + intercept[RuntimeException]: parser("") - } - } - "reject an invalid line" in { - intercept[RuntimeException] { + "reject an invalid line" in: + intercept[RuntimeException]: parser(" 0 17 1 0 0:27.50 /usr/sbin/syslogd") - } - } - "parse a valid line" in { + "parse a valid line" in: assert(parser(" 0 17 1 0 Thu04PM ?? 0:27.50 /usr/sbin/syslogd arg1 arg2") == (17, 1, "/usr/sbin/syslogd arg1 arg2")) - } - } - } end ParseLineSpec diff --git a/src/test/scala/common/PrintSpec.scala b/src/test/scala/common/PrintSpec.scala index 9369c1c..d24a124 100644 --- a/src/test/scala/common/PrintSpec.scala +++ b/src/test/scala/common/PrintSpec.scala @@ -13,39 +13,32 @@ class PrintSpec extends AnyWordSpec with IO: def fixture() = new StringWriter - "The string writer" when { - "when used through a buffered writer" should { - "return the output as a string" in { + "The string writer" when: + "when used through a buffered writer" should: + "return the output as a string" in: val f = fixture() val bw = swToBw(f) bw.append("asdf") bw.flush() assert(f.toString == "asdf") - } - } - } - "The tree printer" when { - "given an empty tree" should { - "print this tree correctly" in { + "The tree printer" when: + "given an empty tree" should: + "print this tree correctly" in: val f = fixture() given BufferedWriter = swToBw(f) printTree(TreeFixtures.empty) assert(f.toString == "") - } - } - "given a simple tree" should { - "print this tree correctly" in { + "given a simple tree" should: + "print this tree correctly" in: val f = fixture() given BufferedWriter = swToBw(f) printTree(TreeFixtures.simple) assert(f.toString == "1: cmd" + EOL) - } - } - "given a complex tree" should { - "print this tree correctly" in { + "given a complex tree" should: + "print this tree correctly" in: val f = fixture() given BufferedWriter = swToBw(f) printTree(TreeFixtures.complex) @@ -55,8 +48,5 @@ class PrintSpec extends AnyWordSpec with IO: | 3: cmd3 | 4: cmd4 |""".stripMargin) - } - } - } end PrintSpec diff --git a/src/test/scala/common/TreeBuilderSpec.scala b/src/test/scala/common/TreeBuilderSpec.scala index cfef284..43659bf 100644 --- a/src/test/scala/common/TreeBuilderSpec.scala +++ b/src/test/scala/common/TreeBuilderSpec.scala @@ -8,28 +8,21 @@ abstract class TreeBuilderSpec(label: String) extends AnyWordSpec with TreeBuild given CanEqual[ProcessTree, ProcessTree] = CanEqual.derived - "The " + label + " tree builder" when { - "given an empty list of processes" should { - "build the correct process tree" in { + "The " + label + " tree builder" when: + "given an empty list of processes" should: + "build the correct process tree" in: assert(buildTree(Iterator.empty) == TreeFixtures.empty) - } - } - "given a simple list of processes" should { - "build the correct process tree" in { + "given a simple list of processes" should: + "build the correct process tree" in: val processes = Iterator((1, 0, "cmd")) assert(buildTree(processes) == TreeFixtures.simple) - } - } - "given a complex list of processes" should { - "build the correct process tree" in { + "given a complex list of processes" should: + "build the correct process tree" in: val processes = Iterator( (1, 0, "cmd1"), (2, 1, "cmd2"), (3, 1, "cmd3"), (4, 3, "cmd4") ) assert(buildTree(processes) == TreeFixtures.complex) - } - } - } end TreeBuilderSpec diff --git a/src/test/scala/fakeps/Spec.scala b/src/test/scala/fakeps/Spec.scala index c5c3c10..1914915 100644 --- a/src/test/scala/fakeps/Spec.scala +++ b/src/test/scala/fakeps/Spec.scala @@ -15,10 +15,9 @@ class Spec extends AnyFunSuite: (ps.get(1) == Some(0)) && (ps - 1).values.forall(ps.contains(_)) def testFakePs(f: FakePS, label: String): Unit = - test(label + " should return a proper flattened ps tree") { + test(label + " should return a proper flattened ps tree"): for s <- sizes do assert(isFlattenedTree(f(s))) - } testFakePs(fakePsFoldSlow, "fakePsFoldSlow") testFakePs(fakePsFold, "fakePsFold")