diff --git a/README.md b/README.md index 5546315..84929c7 100644 --- a/README.md +++ b/README.md @@ -118,12 +118,18 @@ That's it (_potentially_)! Eisner is capable of scanning your classes searching - fields or zero-arg methods that return `java.util.function.Supplier[org.apache.kafka.streams.Topology]` SVGs will be created for each, named after the class(+field/method) that defines the Topology. -Currently, files are generated in `target/streams/_global/eisner/_global/streams/`. +Files are generated by default in `target/eisner`. +As long as topologies are not changed between subsequent runs of `eisner` (without `clean`), SVGs will not be regenerated. ## Tweaking with it Currently, Eisner supports a handful of options, namely: +- `eisnerColorSink`: a `String` representing a [valid graphviz color](https://www.graphviz.org/doc/info/colors.html) used to draw sinks, defaults to `black` +- `eisnerColorSubtopology`: a `String` representing a [valid graphviz color](https://www.graphviz.org/doc/info/colors.html) used to frame sub topologies, defaults to `lightgrey` +- `eisnerColorTopic`: a `String` representing a [valid graphviz color](https://www.graphviz.org/doc/info/colors.html) used to draw topics, defaults to `black` +- `eisnerRoughSVG`: a `Boolean` indicating whether Eisner should produce SVGs that look like hand drawings, defaults to `true` +- `eisnerTargetDirectory`: a `File` which represents the directory where all SVGs will be saved into, defaults to `[current project]/target/eisner` - `eisnerTopologies`: a `Seq[String]` representing the fully qualified names of classes implementing `org.apache.kafka.streams.Topology`. This is useful in all cases where you need to control which SVGs get generated - `eisnerTopologiesSnippet`: a `Option[String]` representing a Scala snippet (inclusive of all necessary imports) that evaluates to a `Seq[(String, org.apache.kafka.streams.Topology)]`, where the `String` represents the `package.name` you want to give to the target file (dots will be converted to path separators). This is useful in all cases where automatic classloader scanning would not work, e.g. because you define your topologies in non zero-args methods or in fields that return `scala.Function1`. See [here](https://raw.githubusercontent.com/laserdisc-io/eisner/master/src/sbt-test/sbt-eisner/snippet/src/main/scala/snippet/EisnerTopology.scala) for a practical example. diff --git a/build.sbt b/build.sbt index 5661b6d..b7d6dfd 100644 --- a/build.sbt +++ b/build.sbt @@ -24,6 +24,7 @@ lazy val eisner = project Compile / unmanagedSourceDirectories += (Compile / sourceDirectory).value / (if (isJDK9Plus) "scala-jdk9+" else "scala-jdk8-"), scalaVersion := `scala 2.12`, libraryDependencies ++= Seq( + "com.chuusai" %% "shapeless" % "2.3.3", "io.circe" %% "circe-generic-extras" % "0.12.2", "io.circe" %% "circe-parser" % "0.12.3", "io.dylemma" %% "xml-spac" % "0.7", diff --git a/src/main/scala/eisner/Config.scala b/src/main/scala/eisner/Config.scala new file mode 100644 index 0000000..4dd57c0 --- /dev/null +++ b/src/main/scala/eisner/Config.scala @@ -0,0 +1,3 @@ +package eisner + +final case class Config(subgraphColor: String, topicColor: String, storeColor: String) diff --git a/src/main/scala/eisner/EisnerPlugin.scala b/src/main/scala/eisner/EisnerPlugin.scala index b580dee..d8f1f59 100644 --- a/src/main/scala/eisner/EisnerPlugin.scala +++ b/src/main/scala/eisner/EisnerPlugin.scala @@ -13,21 +13,31 @@ import scala.concurrent.ExecutionContext.Implicits.global object EisnerPlugin extends AutoPlugin with ReflectionSupport with SnippetSupport { object autoImport { - val eisnerTopologies = settingKey[Seq[String]]("The fully qualified names of classes implementing org.apache.kafka.streams.Topology") + val eisnerColorSink = settingKey[String]("The color used to represent sinks, see https://www.graphviz.org/doc/info/colors.html") + val eisnerColorSubtopology = settingKey[String]("The color used to frame subtopologies, see https://www.graphviz.org/doc/info/colors.html") + val eisnerColorTopic = settingKey[String]("The color used to represent topics, see https://www.graphviz.org/doc/info/colors.html") + val eisnerRoughSVG = settingKey[Boolean]("The flag that controls whether to create SVG using pseudo hand-drawing") + val eisnerTargetDirectory = settingKey[File]("The directory where to store the generated topologies") + val eisnerTopologies = settingKey[Seq[String]]("The fully qualified names of classes implementing org.apache.kafka.streams.Topology") val eisnerTopologiesSnippet = settingKey[Option[String]]("A scala snippet (including all imports) that evaluates to a Seq[(String, org.apache.kafka.streams.Topology)]") - val eisner = taskKey[Seq[File]]("Generates one SVG for each org.apache.kafka.streams.Topology") + val eisner = taskKey[Set[File]]("Generates one SVG for each org.apache.kafka.streams.Topology") } import autoImport._ override final def projectSettings: Seq[Setting[_]] = Seq( + eisnerColorSink := "black", + eisnerColorSubtopology := "lightgrey", + eisnerColorTopic := "black", + eisnerRoughSVG := true, + eisnerTargetDirectory := (Compile / target).value / "eisner", eisnerTopologies := Seq.empty, eisnerTopologiesSnippet := None, eisner := generate.dependsOn(Compile / compile).value ) - private[this] final def generate: Def.Initialize[Task[Seq[File]]] = Def.taskDyn { + private[this] final def generate: Def.Initialize[Task[Set[File]]] = Def.taskDyn { val log = streams.value.log val cacheDir = streams.value.cacheDirectory @@ -59,18 +69,38 @@ object EisnerPlugin extends AutoPlugin with ReflectionSupport with SnippetSuppor Thread.currentThread.setContextClassLoader(classOf[PromiseException].getClassLoader) if (topologyDescriptions.nonEmpty) { - val fs = Future.traverse(topologyDescriptions) { - case (topologyName, topology) => - topology.toSVG.map { svg => - val f = new File(s"$cacheDir/${dotsToSlashes(topologyName)}.svg") - IO.write(f, svg) - f - } + val config = Config(eisnerColorSubtopology.value, eisnerColorTopic.value, eisnerColorSink.value) + val topologiesWithDots = topologyDescriptions + .map { + case (n, td) => (n, td, td.toDot(config)) + } + .collect { + case (n, td, Right(d)) => (n, td, d) + } + val inputs = topologiesWithDots.map { + case (name, _, dot) => + val f = new File(s"$cacheDir/${dotsToSlashes(name)}.dot") + IO.write(f, dot) + f + }.toSet + val cachedFun = FileFunction.cached(cacheDir, FileInfo.hash) { _ => + val fs = Future.traverse(topologiesWithDots) { + case (topologyName, topology, _) => + val svg = if (eisnerRoughSVG.value) topology.toSimplifiedRoughSVG(config) else topology.toSVG(config) + svg.map { svg => + val filename = s"${eisnerTargetDirectory.value.getAbsolutePath}/${dotsToSlashes(topologyName)}.svg" + log.info(s"Eisner - saving $filename") + val f = new File(filename) + IO.write(f, svg) + f + } + } + Await.result(fs, 60.seconds).toSet } - Await.result(fs, 60.seconds) + cachedFun(inputs) } else { log.warn("Eisner - No topology found!") - Seq.empty + Set.empty } } } diff --git a/src/main/scala/eisner/dot/dot.scala b/src/main/scala/eisner/dot/dot.scala index 1ee269b..cf8e63b 100644 --- a/src/main/scala/eisner/dot/dot.scala +++ b/src/main/scala/eisner/dot/dot.scala @@ -17,21 +17,21 @@ package object dot { final def unapplySeq(s: String): Option[Seq[String]] = Some(s.split(',').flatMap(Clean.unapply).filter(_ != "none")) } - final def toDot(s: String): TopologyParserError | DiGraph = { + final def toDot(c: Config, s: String): TopologyParserError | DiGraph = { if (!s.startsWith("Topolog")) Left(TopologyParserError(s"Supplied string does not appear to be a valid topology (${s.substring(0, 10)}...)")) else { val (g, _) = s.split('\n').foldLeft(DiGraph.empty -> (None: Option[String])) { case ((DiGraph(sgs, es, ts, ss), maybeN), SubTopology(Clean(sc), id)) => - DiGraph(SubGraph.empty(id, sc) :: sgs, es, ts, ss) -> maybeN + DiGraph(SubGraph.empty(id, sc, c.subgraphColor) :: sgs, es, ts, ss) -> maybeN case ((DiGraph(sgs, es, ts, ss), _), Source(Clean(n), Links(ls @ _*))) => - DiGraph(sgs, es ++ ls.map(Edge(_, n)), ts ++ ls.map(Topic(_)), ss) -> Some(n) + DiGraph(sgs, es ++ ls.map(Edge(_, n)), ts ++ ls.map(Topic(_, c.topicColor)), ss) -> Some(n) case ((DiGraph(sgs, es, ts, ss), _), Processor(Clean(n), Links(ls @ _*))) => - DiGraph(sgs, es ++ ls.map(Edge(n, _)), ts, ss ++ ls.map(Store(_))) -> Some(n) + DiGraph(sgs, es ++ ls.map(Edge(n, _)), ts, ss ++ ls.map(Store(_, c.storeColor))) -> Some(n) case ((DiGraph(sgs, es, ts, ss), _), Sink(Clean(n), Links(l))) => - DiGraph(sgs, es :+ Edge(n, l), ts + Topic(l), ss) -> Some(n) - case ((DiGraph(SubGraph(id, la, sges) :: sgs, es, ts, ss), Some(n)), RightArrow(Links(ls @ _*))) => - DiGraph(SubGraph(id, la, sges ++ ls.map(Edge(n, _))) :: sgs, es, ts, ss) -> Some(n) + DiGraph(sgs, es :+ Edge(n, l), ts + Topic(l, c.topicColor), ss) -> Some(n) + case ((DiGraph(SubGraph(id, la, sges, color) :: sgs, es, ts, ss), Some(n)), RightArrow(Links(ls @ _*))) => + DiGraph(SubGraph(id, la, sges ++ ls.map(Edge(n, _)), color) :: sgs, es, ts, ss) -> Some(n) case (acc, _) => acc } diff --git a/src/main/scala/eisner/dot/model.scala b/src/main/scala/eisner/dot/model.scala index 2d6485b..71f403e 100644 --- a/src/main/scala/eisner/dot/model.scala +++ b/src/main/scala/eisner/dot/model.scala @@ -18,16 +18,16 @@ final object DiGraph { } } -final case class SubGraph(id: String, label: String, edges: Vector[Edge]) +final case class SubGraph(id: String, label: String, edges: Vector[Edge], color: String) final object SubGraph { - final def empty(id: String, label: String): SubGraph = SubGraph(id, label, Vector.empty) + final def empty(id: String, label: String, color: String): SubGraph = SubGraph(id, label, Vector.empty, color) implicit final val subgraphWriter: Writer[SubGraph] = Writer.instance { - case (SubGraph(id, l, es), i) => + case (SubGraph(id, l, es, c), i) => s"${i.tabs}subgraph cluster_$id {" :: s"""${(i + 1).tabs}label = "$l";""" :: s"${(i + 1).tabs}style = filled;" :: - s"${(i + 1).tabs}color = lightgrey;" :: + s"${(i + 1).tabs}color = $c;" :: s"${(i + 1).tabs}node [style = filled, color = white];" :: Writer[Vector[Edge]].write(es, i + 1) ::: s"${i.tabs}}" :: @@ -40,12 +40,14 @@ final object Edge { implicit final val edgeWriter: Writer[Edge] = Writer.instance { case (Edge(f, t), i) => s"""${i.tabs}"$f" -> "$t";""" :: Nil } } -final case class Topic(name: String) extends AnyVal +final case class Topic(name: String, color: String) final object Topic { - implicit final val topicWriter: Writer[Topic] = Writer.instance { case (Topic(t), i) => s"""${i.tabs}"$t" [shape = rect];""" :: Nil } + implicit final val topicWriter: Writer[Topic] = Writer.instance { case (Topic(t, c), i) => s"""${i.tabs}"$t" [shape = rect; color = $c];""" :: Nil } } -final case class Store(name: String) extends AnyVal +final case class Store(name: String, color: String) final object Store { - implicit final val storeWriter: Writer[Store] = Writer.instance { case (Store(s), i) => s"""${i.tabs}"$s" [shape = cylinder];""" :: Nil } + implicit final val storeWriter: Writer[Store] = Writer.instance { + case (Store(s, c), i) => s"""${i.tabs}"$s" [shape = cylinder; color = $c];""" :: Nil + } } diff --git a/src/main/scala/eisner/eisner.scala b/src/main/scala/eisner/eisner.scala index 7d7b527..f6bcfee 100644 --- a/src/main/scala/eisner/eisner.scala +++ b/src/main/scala/eisner/eisner.scala @@ -9,6 +9,13 @@ package object eisner { private[eisner] final val Topic = dot.Topic private[eisner] final val Store = dot.Store + private[this] final val decimalsPattern = """\.(\d{2})\d+(\D?)""".r + private[this] object trimDoubles extends shapeless.poly.->((s: String) => decimalsPattern.replaceAllIn(s, ".$1$2")) + private[this] final def simplify(svg: SVG): SVG = { + val simplified = shapeless.everywhere(trimDoubles)(svg) + simplified + } + implicit final class IntOps(private val i: Int) extends AnyVal { final def tabs: String = "\t" * i } @@ -16,18 +23,22 @@ package object eisner { import io.circe.parser.decode import scala.concurrent.{ExecutionContext, Future} - private[eisner] final def toDiGraph: TopologyParserError | DiGraph = dot.toDot(s) - private[eisner] final def decodeSVG: SVGParserError | SVG = decode[SVG](s).left.map(e => SVGParserError(e.getLocalizedMessage())) + private[eisner] final def toDiGraph(c: Config): TopologyParserError | DiGraph = dot.toDot(c, s) + private[eisner] final def decodeSVG: SVGParserError | SVG = decode[SVG](s).left.map(e => SVGParserError(e.getLocalizedMessage())) - final def toDot: TopologyParserError | String = toDiGraph.map(_.dot) - final def toSVG(implicit ec: ExecutionContext): Future[String] = toDiGraph match { + final def toDot(c: Config): TopologyParserError | String = toDiGraph(c).map(_.dot) + final def toSVG(c: Config)(implicit ec: ExecutionContext): Future[String] = toDiGraph(c) match { case Left(tpe) => Future.failed(tpe) case Right(dg) => dg.simpleSVG.map(_.xml) } - final def toRoughSVG(implicit ec: ExecutionContext): Future[String] = toDiGraph match { + final def toRoughSVG(c: Config)(implicit ec: ExecutionContext): Future[String] = toDiGraph(c) match { case Left(tpe) => Future.failed(tpe) case Right(dg) => dg.simpleSVG.flatMap(_.roughSVG.fold(Future.failed, svg => Future.successful(svg.xml))) } + final def toSimplifiedRoughSVG(c: Config)(implicit ec: ExecutionContext): Future[String] = toDiGraph(c) match { + case Left(tpe) => Future.failed(tpe) + case Right(dg) => dg.simpleSVG.flatMap(_.roughSVG.fold(Future.failed, svg => Future.successful(svg.simplified.xml))) + } } private[eisner] implicit final class DiGraphOps(private val dg: DiGraph) extends AnyVal { import scala.concurrent.{ExecutionContext, Future} @@ -40,6 +51,7 @@ package object eisner { private[eisner] implicit final class SVGOps(private val svg: SVG) extends AnyVal { import io.circe.Encoder + final def simplified: SVG = simplify(svg) final def json: String = Encoder[SVG].apply(svg).noSpaces final def xml: String = Writer[SVG].write(svg, 0).mkString("\n") final def roughSVG: SVGParserError | SVG = js.svgToRoughSVG(json).decodeSVG diff --git a/src/sbt-test/sbt-eisner/auto-field/test b/src/sbt-test/sbt-eisner/auto-field/test index b377418..9a137b5 100644 --- a/src/sbt-test/sbt-eisner/auto-field/test +++ b/src/sbt-test/sbt-eisner/auto-field/test @@ -1,4 +1,4 @@ # invoke SVG creation > eisner # check that the SVG is created -$ exists target/streams/_global/eisner/_global/streams/auto/field/InnerTopology#someField.svg \ No newline at end of file +$ exists target/eisner/auto/field/InnerTopology#someField.svg \ No newline at end of file diff --git a/src/sbt-test/sbt-eisner/auto-fun0field/test b/src/sbt-test/sbt-eisner/auto-fun0field/test index 505f724..9ff305f 100644 --- a/src/sbt-test/sbt-eisner/auto-fun0field/test +++ b/src/sbt-test/sbt-eisner/auto-fun0field/test @@ -1,4 +1,4 @@ # invoke SVG creation > eisner # check that the SVG is created -$ exists target/streams/_global/eisner/_global/streams/auto/fun0field/InnerTopology#someField.svg \ No newline at end of file +$ exists target/eisner/auto/fun0field/InnerTopology#someField.svg \ No newline at end of file diff --git a/src/sbt-test/sbt-eisner/auto-fun0method/test b/src/sbt-test/sbt-eisner/auto-fun0method/test index 16241b3..5566584 100644 --- a/src/sbt-test/sbt-eisner/auto-fun0method/test +++ b/src/sbt-test/sbt-eisner/auto-fun0method/test @@ -1,4 +1,4 @@ # invoke SVG creation > eisner # check that the SVG is created -$ exists target/streams/_global/eisner/_global/streams/auto/fun0method/InnerTopology$someMethod.svg \ No newline at end of file +$ exists target/eisner/auto/fun0method/InnerTopology$someMethod.svg \ No newline at end of file diff --git a/src/sbt-test/sbt-eisner/auto-inheritance/test b/src/sbt-test/sbt-eisner/auto-inheritance/test index 2c79d21..fab250a 100644 --- a/src/sbt-test/sbt-eisner/auto-inheritance/test +++ b/src/sbt-test/sbt-eisner/auto-inheritance/test @@ -1,4 +1,4 @@ # invoke SVG creation > eisner # check that the SVG is created -$ exists target/streams/_global/eisner/_global/streams/auto/inheritance/EisnerTopology.svg \ No newline at end of file +$ exists target/eisner/auto/inheritance/EisnerTopology.svg \ No newline at end of file diff --git a/src/sbt-test/sbt-eisner/auto-method/test b/src/sbt-test/sbt-eisner/auto-method/test index dbaeba3..ca8a162 100644 --- a/src/sbt-test/sbt-eisner/auto-method/test +++ b/src/sbt-test/sbt-eisner/auto-method/test @@ -1,4 +1,4 @@ # invoke SVG creation > eisner # check that the SVG is created -$ exists target/streams/_global/eisner/_global/streams/auto/method/InnerTopology$someMethod.svg \ No newline at end of file +$ exists target/eisner/auto/method/InnerTopology$someMethod.svg \ No newline at end of file diff --git a/src/sbt-test/sbt-eisner/auto-supplierfield/test b/src/sbt-test/sbt-eisner/auto-supplierfield/test index e68e8ae..ab13580 100644 --- a/src/sbt-test/sbt-eisner/auto-supplierfield/test +++ b/src/sbt-test/sbt-eisner/auto-supplierfield/test @@ -1,4 +1,4 @@ # invoke SVG creation > eisner # check that the SVG is created -$ exists target/streams/_global/eisner/_global/streams/auto/supplierfield/InnerTopology#someField.svg \ No newline at end of file +$ exists target/eisner/auto/supplierfield/InnerTopology#someField.svg \ No newline at end of file diff --git a/src/sbt-test/sbt-eisner/auto-suppliermethod/test b/src/sbt-test/sbt-eisner/auto-suppliermethod/test index e957efb..6ebbcce 100644 --- a/src/sbt-test/sbt-eisner/auto-suppliermethod/test +++ b/src/sbt-test/sbt-eisner/auto-suppliermethod/test @@ -1,4 +1,4 @@ # invoke SVG creation > eisner # check that the SVG is created -$ exists target/streams/_global/eisner/_global/streams/auto/suppliermethod/InnerTopology$someMethod.svg \ No newline at end of file +$ exists target/eisner/auto/suppliermethod/InnerTopology$someMethod.svg \ No newline at end of file diff --git a/src/sbt-test/sbt-eisner/empty/test b/src/sbt-test/sbt-eisner/empty/test index cc7b4b8..8e4c57f 100644 --- a/src/sbt-test/sbt-eisner/empty/test +++ b/src/sbt-test/sbt-eisner/empty/test @@ -1,4 +1,4 @@ # invoke SVG creation > eisner # check that the SVG is not created (topology is empty) -$ absent target/streams/_global/eisner/_global/streams/EmptyTopology.svg \ No newline at end of file +$ absent target/eisner/EmptyTopology.svg \ No newline at end of file diff --git a/src/sbt-test/sbt-eisner/explicit-inheritance/test b/src/sbt-test/sbt-eisner/explicit-inheritance/test index f5565b3..e9317e2 100644 --- a/src/sbt-test/sbt-eisner/explicit-inheritance/test +++ b/src/sbt-test/sbt-eisner/explicit-inheritance/test @@ -1,4 +1,4 @@ # invoke SVG creation > eisner # check that the SVG is created -$ exists target/streams/_global/eisner/_global/streams/explicit/inheritance/EisnerTopology.svg \ No newline at end of file +$ exists target/eisner/explicit/inheritance/EisnerTopology.svg \ No newline at end of file diff --git a/src/sbt-test/sbt-eisner/snippet/test b/src/sbt-test/sbt-eisner/snippet/test index ab39155..c15f19d 100644 --- a/src/sbt-test/sbt-eisner/snippet/test +++ b/src/sbt-test/sbt-eisner/snippet/test @@ -1,4 +1,4 @@ # invoke SVG creation > eisner # check that the SVG is created -$ exists target/streams/_global/eisner/_global/streams/snippet/EisnerTopology#myTopology.svg \ No newline at end of file +$ exists target/eisner/snippet/EisnerTopology#myTopology.svg \ No newline at end of file diff --git a/src/test/resources/topology1-rough.svg b/src/test/resources/topology1-rough.svg index 4fe3a8e..babcf92 100644 --- a/src/test/resources/topology1-rough.svg +++ b/src/test/resources/topology1-rough.svg @@ -1,161 +1,157 @@ + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + - - Kafka Streams Topology - - + + Sub- topology: 0 - - + + Sub- topology: 1 - + KSTREAM- SOURCE- 0000000000 - + KSTREAM- TRANSFORM- 0000000001 - - - - + + + + KSTREAM- KEY- SELECT- 0000000002 - - - - - + + + + + conversation- meta- state - - - - + + + + KSTREAM- FILTER- 0000000005 - - - - + + + + KSTREAM- SINK- 0000000004 - - - - + + + + count- resolved- repartition - - - - + + + + KSTREAM- SOURCE- 0000000006 - + KSTREAM- AGGREGATE- 0000000003 - - - - + + + + KTABLE- TOSTREAM- 0000000007 - - - - - + + + + + count- resolved - - - - + + + + KSTREAM- SINK- 0000000008 - - - - + + + + streams- count- resolved - - - - + + + + conversation- meta - - - - - - + + + + + + \ No newline at end of file diff --git a/src/test/resources/topology1-simplified-rough.svg b/src/test/resources/topology1-simplified-rough.svg new file mode 100644 index 0000000..36d56f7 --- /dev/null +++ b/src/test/resources/topology1-simplified-rough.svg @@ -0,0 +1,157 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Kafka Streams Topology + + + Sub- + topology: 0 + + + Sub- + topology: 1 + + KSTREAM- + SOURCE- + 0000000000 + + KSTREAM- + TRANSFORM- + 0000000001 + + + + + KSTREAM- + KEY- + SELECT- + 0000000002 + + + + + + conversation- + meta- + state + + + + + KSTREAM- + FILTER- + 0000000005 + + + + + KSTREAM- + SINK- + 0000000004 + + + + + count- + resolved- + repartition + + + + + KSTREAM- + SOURCE- + 0000000006 + + KSTREAM- + AGGREGATE- + 0000000003 + + + + + KTABLE- + TOSTREAM- + 0000000007 + + + + + + count- + resolved + + + + + KSTREAM- + SINK- + 0000000008 + + + + + streams- + count- + resolved + + + + + conversation- + meta + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/topology1.dot b/src/test/resources/topology1.dot index 1e204c3..d01499b 100644 --- a/src/test/resources/topology1.dot +++ b/src/test/resources/topology1.dot @@ -25,9 +25,9 @@ digraph G { "count-\nresolved-\nrepartition" -> "KSTREAM-\nSOURCE-\n0000000006"; "KSTREAM-\nAGGREGATE-\n0000000003" -> "count-\nresolved"; "KSTREAM-\nSINK-\n0000000008" -> "streams-\ncount-\nresolved"; - "conversation-\nmeta" [shape = rect]; - "count-\nresolved-\nrepartition" [shape = rect]; - "streams-\ncount-\nresolved" [shape = rect]; - "conversation-\nmeta-\nstate" [shape = cylinder]; - "count-\nresolved" [shape = cylinder]; + "conversation-\nmeta" [shape = rect; color = black]; + "count-\nresolved-\nrepartition" [shape = rect; color = black]; + "streams-\ncount-\nresolved" [shape = rect; color = black]; + "conversation-\nmeta-\nstate" [shape = cylinder; color = black]; + "count-\nresolved" [shape = cylinder; color = black]; } \ No newline at end of file diff --git a/src/test/resources/topology2-rough.svg b/src/test/resources/topology2-rough.svg index 33c8b73..b144420 100644 --- a/src/test/resources/topology2-rough.svg +++ b/src/test/resources/topology2-rough.svg @@ -1,101 +1,97 @@ + - + - + - + - + - + - + - + - + - - - - + - - Kafka Streams Topology - - + + Sub- topology: 0 - - + + Sub- topology: 1 - + KSTREAM- SOURCE- 0000000002 - + KSTREAM- LEFTJOIN- 0000000003 - - - - + + + + KSTREAM- SINK- 0000000004 - - - - + + + + skus- with- taxcode - - - - + + + + KTABLE- SOURCE- 0000000000 - + KTABLE- SOURCE- 0000000001 - - - - - + + + + + tax- codes- store - - - - + + + + skus - - - - + + + + taxcodes - - - + + + \ No newline at end of file diff --git a/src/test/resources/topology2-simplified-rough.svg b/src/test/resources/topology2-simplified-rough.svg new file mode 100644 index 0000000..6c36b43 --- /dev/null +++ b/src/test/resources/topology2-simplified-rough.svg @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Kafka Streams Topology + + + Sub- + topology: 0 + + + Sub- + topology: 1 + + KSTREAM- + SOURCE- + 0000000002 + + KSTREAM- + LEFTJOIN- + 0000000003 + + + + + KSTREAM- + SINK- + 0000000004 + + + + + skus- + with- + taxcode + + + + + KTABLE- + SOURCE- + 0000000000 + + KTABLE- + SOURCE- + 0000000001 + + + + + + tax- + codes- + store + + + + + skus + + + + + taxcodes + + + + + \ No newline at end of file diff --git a/src/test/resources/topology2.dot b/src/test/resources/topology2.dot index 4e06a62..6be6950 100644 --- a/src/test/resources/topology2.dot +++ b/src/test/resources/topology2.dot @@ -19,8 +19,8 @@ digraph G { "KSTREAM-\nSINK-\n0000000004" -> "skus-\nwith-\ntaxcode"; "taxcodes" -> "KTABLE-\nSOURCE-\n0000000000"; "KTABLE-\nSOURCE-\n0000000001" -> "tax-\ncodes-\nstore"; - "skus" [shape = rect]; - "skus-\nwith-\ntaxcode" [shape = rect]; - "taxcodes" [shape = rect]; - "tax-\ncodes-\nstore" [shape = cylinder]; + "skus" [shape = rect; color = black]; + "skus-\nwith-\ntaxcode" [shape = rect; color = black]; + "taxcodes" [shape = rect; color = black]; + "tax-\ncodes-\nstore" [shape = cylinder; color = black]; } \ No newline at end of file diff --git a/src/test/resources/topology3-rough.svg b/src/test/resources/topology3-rough.svg index 4f2eba8..ccf23a6 100644 --- a/src/test/resources/topology3-rough.svg +++ b/src/test/resources/topology3-rough.svg @@ -1,210 +1,206 @@ + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + - - Kafka Streams Topology - - + + Sub- topology: 0 - - + + Sub- topology: 1 - + KSTREAM- SOURCE- 0000000000 - + KSTREAM- KEY- SELECT- 0000000001 - - - - + + + + KSTREAM- FILTER- 0000000019 - - - - + + + + KSTREAM- SINK- 0000000018 - - - - + + + + count- store- repartition - - - - + + + + KSTREAM- SOURCE- 0000000020 - + KSTREAM- AGGREGATE- 0000000002 - - - - + + + + KSTREAM- AGGREGATE- 0000000010 - - - - + + + + KTABLE- MAPVALUES- 0000000007 - - - - - + + + + + count- store - - - - + + + + KTABLE- MAPVALUES- 0000000015 - - - - - + + + + + windowed- count- store - - - - + + + + KTABLE- TOSTREAM- 0000000008 - - - - + + + + KTABLE- TOSTREAM- 0000000016 - - - - + + + + KSTREAM- SINK- 0000000009 - - - - + + + + KSTREAM- SINK- 0000000017 - - - - + + + + count- topic - - - - + + + + windowed- count - - - - + + + + streams- plaintext- input - - - - - - + + + + + + \ No newline at end of file diff --git a/src/test/resources/topology3-simplified-rough.svg b/src/test/resources/topology3-simplified-rough.svg new file mode 100644 index 0000000..2bd00f8 --- /dev/null +++ b/src/test/resources/topology3-simplified-rough.svg @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Kafka Streams Topology + + + Sub- + topology: 0 + + + Sub- + topology: 1 + + KSTREAM- + SOURCE- + 0000000000 + + KSTREAM- + KEY- + SELECT- + 0000000001 + + + + + KSTREAM- + FILTER- + 0000000019 + + + + + KSTREAM- + SINK- + 0000000018 + + + + + count- + store- + repartition + + + + + KSTREAM- + SOURCE- + 0000000020 + + KSTREAM- + AGGREGATE- + 0000000002 + + + + + KSTREAM- + AGGREGATE- + 0000000010 + + + + + KTABLE- + MAPVALUES- + 0000000007 + + + + + + count- + store + + + + + KTABLE- + MAPVALUES- + 0000000015 + + + + + + windowed- + count- + store + + + + + KTABLE- + TOSTREAM- + 0000000008 + + + + + KTABLE- + TOSTREAM- + 0000000016 + + + + + KSTREAM- + SINK- + 0000000009 + + + + + KSTREAM- + SINK- + 0000000017 + + + + + count- + topic + + + + + windowed- + count + + + + + streams- + plaintext- + input + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/topology3.dot b/src/test/resources/topology3.dot index a483677..0813296 100644 --- a/src/test/resources/topology3.dot +++ b/src/test/resources/topology3.dot @@ -30,10 +30,10 @@ digraph G { "KSTREAM-\nAGGREGATE-\n0000000010" -> "windowed-\ncount-\nstore"; "KSTREAM-\nSINK-\n0000000009" -> "count-\ntopic"; "KSTREAM-\nSINK-\n0000000017" -> "windowed-\ncount"; - "streams-\nplaintext-\ninput" [shape = rect]; - "count-\nstore-\nrepartition" [shape = rect]; - "count-\ntopic" [shape = rect]; - "windowed-\ncount" [shape = rect]; - "count-\nstore" [shape = cylinder]; - "windowed-\ncount-\nstore" [shape = cylinder]; + "streams-\nplaintext-\ninput" [shape = rect; color = black]; + "count-\nstore-\nrepartition" [shape = rect; color = black]; + "count-\ntopic" [shape = rect; color = black]; + "windowed-\ncount" [shape = rect; color = black]; + "count-\nstore" [shape = cylinder; color = black]; + "windowed-\ncount-\nstore" [shape = cylinder; color = black]; } \ No newline at end of file diff --git a/src/test/resources/topology4-rough.svg b/src/test/resources/topology4-rough.svg index 90b947c..e9f796c 100644 --- a/src/test/resources/topology4-rough.svg +++ b/src/test/resources/topology4-rough.svg @@ -1,698 +1,694 @@ + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + - - Kafka Streams Topology - - + + Sub- topology: 0 - - + + Sub- topology: 1 - - + + Sub- topology: 2 - - + + Sub- topology: 3 - - + + Sub- topology: 4 - + KSTREAM- SOURCE- 0000000000 - + KSTREAM- FLATMAP- 0000000001 - - - - + + + + KSTREAM- FILTER- 0000000012 - - - - + + + + KSTREAM- FILTER- 0000000020 - - - - + + + + KSTREAM- SINK- 0000000011 - - - - + + + + KSTREAM- SINK- 0000000019 - - - - + + + + KSTREAM- REDUCE- STATE- STORE- 0000000009- repartition - - - - + + + + KSTREAM- FLATMAP- 0000000001- repartition - - - - + + + + KSTREAM- SOURCE- 0000000002 - + KSTREAM- FLATMAP- 0000000003 - - - - + + + + KSTREAM- FILTER- 0000000017 - - - - + + + + KSTREAM- FILTER- 0000000032 - - - - + + + + KSTREAM- SINK- 0000000016 - - - - + + + + KSTREAM- SINK- 0000000031 - - - - + + + + KSTREAM- REDUCE- STATE- STORE- 0000000014- repartition - - - - + + + + KSTREAM- FLATMAP- 0000000003- repartition - - - - + + + + KSTREAM- SOURCE- 0000000004 - + KSTREAM- FLATMAP- 0000000005 - - - - + + + + KSTREAM- FILTER- 0000000038 - - - - + + + + KSTREAM- SINK- 0000000006 - - - - + + + + KSTREAM- SINK- 0000000037 - - - - + + + + tblDeptTopic - - - - + + + + KSTREAM- FLATMAP- 0000000005- repartition - - - - + + + + KSTREAM- SOURCE- 0000000021 - + KSTREAM- LEFTJOIN- 0000000022 - - - - + + + + KSTREAM- FLATMAPVALUES- 0000000023 - - - - - + + + + + KSTREAM- REDUCE- STATE- STORE- 0000000014 - - - - + + + + KSTREAM- KEY- SELECT- 0000000024 - - - - + + + + KSTREAM- LEFTJOIN- 0000000030 - - - - + + + + KSTREAM- FILTER- 0000000028 - - - - + + + + KSTREAM- MERGE- 0000000043 - - - - + + + + KSTREAM- SOURCE- 0000000033 - + KSTREAM- LEFTJOIN- 0000000034 - - - - + + + + KSTREAM- FLATMAPVALUES- 0000000035 - - - - - + + + + + KSTREAM- REDUCE- STATE- STORE- 0000000009 - - - - + + + + KSTREAM- LEFTJOIN- 0000000036 - - - - + + + + KSTREAM- SOURCE- 0000000039 - + KSTREAM- LEFTJOIN- 0000000040 - - - - + + + + KSTREAM- FLATMAPVALUES- 0000000041 - - - - - + + + + + KSTREAM- REDUCE- STATE- STORE- 0000000025 - - - - - - - + + + + + + + KSTREAM- KEY- SELECT- 0000000042 - - - - + + + + KSTREAM- MERGE- 0000000044 - - - - - - - + + + + + + + KSTREAM- FILTER- 0000000048 - - - - + + + + KSTREAM- SINK- 0000000027 - - - - + + + + KSTREAM- SINK- 0000000047 - - - - + + + + KSTREAM- REDUCE- STATE- STORE- 0000000025- repartition - - - - + + + + KSTREAM- REDUCE- STATE- STORE- 0000000045- repartition - - - - + + + + KSTREAM- SOURCE- 0000000013 - + KSTREAM- REDUCE- 0000000010 - - - - - - - + + + + + + + KSTREAM- SOURCE- 0000000018 - + KSTREAM- REDUCE- 0000000015 - - - - - - - + + + + + + + KSTREAM- SOURCE- 0000000029 - + KSTREAM- REDUCE- 0000000026 - - - - - - - + + + + + + + KSTREAM- SOURCE- 0000000049 - + KSTREAM- REDUCE- 0000000046 - - - - + + + + KTABLE- TOSTREAM- 0000000050 - - - - - + + + + + KSTREAM- REDUCE- STATE- STORE- 0000000045 - - - - + + + + KSTREAM- SINK- 0000000051 - - - - + + + + snkItemsTopic - - - - + + + + srcItemsTopic - - - - - - - - - - + + + + + + + + + + srcFeeTopic - - - - - - - - - - + + + + + + + + + + srcDeptTopic - - - - - - - - - - - - + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/topology4-simplified-rough.svg b/src/test/resources/topology4-simplified-rough.svg new file mode 100644 index 0000000..171654a --- /dev/null +++ b/src/test/resources/topology4-simplified-rough.svg @@ -0,0 +1,694 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Kafka Streams Topology + + + Sub- + topology: 0 + + + Sub- + topology: 1 + + + Sub- + topology: 2 + + + Sub- + topology: 3 + + + Sub- + topology: 4 + + KSTREAM- + SOURCE- + 0000000000 + + KSTREAM- + FLATMAP- + 0000000001 + + + + + KSTREAM- + FILTER- + 0000000012 + + + + + KSTREAM- + FILTER- + 0000000020 + + + + + KSTREAM- + SINK- + 0000000011 + + + + + KSTREAM- + SINK- + 0000000019 + + + + + KSTREAM- + REDUCE- + STATE- + STORE- + 0000000009- + repartition + + + + + KSTREAM- + FLATMAP- + 0000000001- + repartition + + + + + KSTREAM- + SOURCE- + 0000000002 + + KSTREAM- + FLATMAP- + 0000000003 + + + + + KSTREAM- + FILTER- + 0000000017 + + + + + KSTREAM- + FILTER- + 0000000032 + + + + + KSTREAM- + SINK- + 0000000016 + + + + + KSTREAM- + SINK- + 0000000031 + + + + + KSTREAM- + REDUCE- + STATE- + STORE- + 0000000014- + repartition + + + + + KSTREAM- + FLATMAP- + 0000000003- + repartition + + + + + KSTREAM- + SOURCE- + 0000000004 + + KSTREAM- + FLATMAP- + 0000000005 + + + + + KSTREAM- + FILTER- + 0000000038 + + + + + KSTREAM- + SINK- + 0000000006 + + + + + KSTREAM- + SINK- + 0000000037 + + + + + tblDeptTopic + + + + + KSTREAM- + FLATMAP- + 0000000005- + repartition + + + + + KSTREAM- + SOURCE- + 0000000021 + + KSTREAM- + LEFTJOIN- + 0000000022 + + + + + KSTREAM- + FLATMAPVALUES- + 0000000023 + + + + + + KSTREAM- + REDUCE- + STATE- + STORE- + 0000000014 + + + + + KSTREAM- + KEY- + SELECT- + 0000000024 + + + + + KSTREAM- + LEFTJOIN- + 0000000030 + + + + + KSTREAM- + FILTER- + 0000000028 + + + + + KSTREAM- + MERGE- + 0000000043 + + + + + KSTREAM- + SOURCE- + 0000000033 + + KSTREAM- + LEFTJOIN- + 0000000034 + + + + + KSTREAM- + FLATMAPVALUES- + 0000000035 + + + + + + KSTREAM- + REDUCE- + STATE- + STORE- + 0000000009 + + + + + KSTREAM- + LEFTJOIN- + 0000000036 + + + + + KSTREAM- + SOURCE- + 0000000039 + + KSTREAM- + LEFTJOIN- + 0000000040 + + + + + KSTREAM- + FLATMAPVALUES- + 0000000041 + + + + + + KSTREAM- + REDUCE- + STATE- + STORE- + 0000000025 + + + + + + + + KSTREAM- + KEY- + SELECT- + 0000000042 + + + + + KSTREAM- + MERGE- + 0000000044 + + + + + + + + KSTREAM- + FILTER- + 0000000048 + + + + + KSTREAM- + SINK- + 0000000027 + + + + + KSTREAM- + SINK- + 0000000047 + + + + + KSTREAM- + REDUCE- + STATE- + STORE- + 0000000025- + repartition + + + + + KSTREAM- + REDUCE- + STATE- + STORE- + 0000000045- + repartition + + + + + KSTREAM- + SOURCE- + 0000000013 + + KSTREAM- + REDUCE- + 0000000010 + + + + + + + + KSTREAM- + SOURCE- + 0000000018 + + KSTREAM- + REDUCE- + 0000000015 + + + + + + + + KSTREAM- + SOURCE- + 0000000029 + + KSTREAM- + REDUCE- + 0000000026 + + + + + + + + KSTREAM- + SOURCE- + 0000000049 + + KSTREAM- + REDUCE- + 0000000046 + + + + + KTABLE- + TOSTREAM- + 0000000050 + + + + + + KSTREAM- + REDUCE- + STATE- + STORE- + 0000000045 + + + + + KSTREAM- + SINK- + 0000000051 + + + + + snkItemsTopic + + + + + srcItemsTopic + + + + + + + + + + + srcFeeTopic + + + + + + + + + + + srcDeptTopic + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/topology4.dot b/src/test/resources/topology4.dot index 9e2b5c2..1c22ded 100644 --- a/src/test/resources/topology4.dot +++ b/src/test/resources/topology4.dot @@ -94,20 +94,20 @@ digraph G { "KSTREAM-\nREDUCE-\nSTATE-\nSTORE-\n0000000045-\nrepartition" -> "KSTREAM-\nSOURCE-\n0000000049"; "KSTREAM-\nREDUCE-\n0000000046" -> "KSTREAM-\nREDUCE-\nSTATE-\nSTORE-\n0000000045"; "KSTREAM-\nSINK-\n0000000051" -> "snkItemsTopic"; - "KSTREAM-\nFLATMAP-\n0000000003-\nrepartition" [shape = rect]; - "KSTREAM-\nFLATMAP-\n0000000005-\nrepartition" [shape = rect]; - "KSTREAM-\nREDUCE-\nSTATE-\nSTORE-\n0000000025-\nrepartition" [shape = rect]; - "KSTREAM-\nREDUCE-\nSTATE-\nSTORE-\n0000000014-\nrepartition" [shape = rect]; - "tblDeptTopic" [shape = rect]; - "srcFeeTopic" [shape = rect]; - "srcDeptTopic" [shape = rect]; - "KSTREAM-\nREDUCE-\nSTATE-\nSTORE-\n0000000045-\nrepartition" [shape = rect]; - "KSTREAM-\nREDUCE-\nSTATE-\nSTORE-\n0000000009-\nrepartition" [shape = rect]; - "snkItemsTopic" [shape = rect]; - "KSTREAM-\nFLATMAP-\n0000000001-\nrepartition" [shape = rect]; - "srcItemsTopic" [shape = rect]; - "KSTREAM-\nREDUCE-\nSTATE-\nSTORE-\n0000000014" [shape = cylinder]; - "KSTREAM-\nREDUCE-\nSTATE-\nSTORE-\n0000000009" [shape = cylinder]; - "KSTREAM-\nREDUCE-\nSTATE-\nSTORE-\n0000000025" [shape = cylinder]; - "KSTREAM-\nREDUCE-\nSTATE-\nSTORE-\n0000000045" [shape = cylinder]; + "KSTREAM-\nREDUCE-\nSTATE-\nSTORE-\n0000000045-\nrepartition" [shape = rect; color = black]; + "KSTREAM-\nFLATMAP-\n0000000001-\nrepartition" [shape = rect; color = black]; + "srcItemsTopic" [shape = rect; color = black]; + "KSTREAM-\nREDUCE-\nSTATE-\nSTORE-\n0000000014-\nrepartition" [shape = rect; color = black]; + "KSTREAM-\nREDUCE-\nSTATE-\nSTORE-\n0000000009-\nrepartition" [shape = rect; color = black]; + "srcDeptTopic" [shape = rect; color = black]; + "KSTREAM-\nREDUCE-\nSTATE-\nSTORE-\n0000000025-\nrepartition" [shape = rect; color = black]; + "KSTREAM-\nFLATMAP-\n0000000003-\nrepartition" [shape = rect; color = black]; + "srcFeeTopic" [shape = rect; color = black]; + "tblDeptTopic" [shape = rect; color = black]; + "KSTREAM-\nFLATMAP-\n0000000005-\nrepartition" [shape = rect; color = black]; + "snkItemsTopic" [shape = rect; color = black]; + "KSTREAM-\nREDUCE-\nSTATE-\nSTORE-\n0000000014" [shape = cylinder; color = black]; + "KSTREAM-\nREDUCE-\nSTATE-\nSTORE-\n0000000009" [shape = cylinder; color = black]; + "KSTREAM-\nREDUCE-\nSTATE-\nSTORE-\n0000000025" [shape = cylinder; color = black]; + "KSTREAM-\nREDUCE-\nSTATE-\nSTORE-\n0000000045" [shape = cylinder; color = black]; } \ No newline at end of file diff --git a/src/test/scala/eisner/BaseEisnerSpec.scala b/src/test/scala/eisner/BaseEisnerSpec.scala index 938f1f7..2699d3b 100644 --- a/src/test/scala/eisner/BaseEisnerSpec.scala +++ b/src/test/scala/eisner/BaseEisnerSpec.scala @@ -8,6 +8,8 @@ import org.scalatest.wordspec.AsyncWordSpec abstract class BaseEisnerSpec(i: Int) extends AsyncWordSpec with Matchers with EitherValues { def expectedDiGraph: DiGraph + val config = Config("lightgrey", "black", "black") + lazy val txt = Source.fromInputStream(getClass.getResourceAsStream(s"/topology$i.txt")).getLines.mkString("\n") lazy val dot = Source.fromInputStream(getClass.getResourceAsStream(s"/topology$i.dot")).getLines.mkString("\n") lazy val svg = Source.fromInputStream(getClass.getResourceAsStream(s"/topology$i.svg")).getLines.mkString("\n") @@ -15,13 +17,13 @@ abstract class BaseEisnerSpec(i: Int) extends AsyncWordSpec with Matchers with E s"Topology #$i" when { "loaded from disk" must { "convert to a valid graph" in { - txt.toDiGraph.right.value shouldBe expectedDiGraph + txt.toDiGraph(config).right.value shouldBe expectedDiGraph } "convert to a valid dot" in { - txt.toDot.right.value shouldBe dot + txt.toDot(config).right.value shouldBe dot } "convert to a valid svg" in { - txt.toSVG.map(_.trim shouldBe svg) + txt.toSVG(config).map(_.trim shouldBe svg) } } } diff --git a/src/test/scala/eisner/ComplexTopologySpec.scala b/src/test/scala/eisner/ComplexTopologySpec.scala index 6cd08de..df4f0ac 100644 --- a/src/test/scala/eisner/ComplexTopologySpec.scala +++ b/src/test/scala/eisner/ComplexTopologySpec.scala @@ -15,7 +15,8 @@ final class ComplexTopologySpec extends BaseEisnerSpec(3) { Edge("KTABLE-\\nMAPVALUES-\\n0000000015", "KTABLE-\\nTOSTREAM-\\n0000000016"), Edge("KTABLE-\\nTOSTREAM-\\n0000000008", "KSTREAM-\\nSINK-\\n0000000009"), Edge("KTABLE-\\nTOSTREAM-\\n0000000016", "KSTREAM-\\nSINK-\\n0000000017") - ) + ), + "lightgrey" ), SubGraph( "0", @@ -24,7 +25,8 @@ final class ComplexTopologySpec extends BaseEisnerSpec(3) { Edge("KSTREAM-\\nSOURCE-\\n0000000000", "KSTREAM-\\nKEY-\\nSELECT-\\n0000000001"), Edge("KSTREAM-\\nKEY-\\nSELECT-\\n0000000001", "KSTREAM-\\nFILTER-\\n0000000019"), Edge("KSTREAM-\\nFILTER-\\n0000000019", "KSTREAM-\\nSINK-\\n0000000018") - ) + ), + "lightgrey" ) ), Vector( @@ -37,14 +39,14 @@ final class ComplexTopologySpec extends BaseEisnerSpec(3) { Edge("KSTREAM-\\nSINK-\\n0000000017", "windowed-\\ncount") ), Set( - Topic("streams-\\nplaintext-\\ninput"), - Topic("count-\\nstore-\\nrepartition"), - Topic("count-\\ntopic"), - Topic("windowed-\\ncount") + Topic("streams-\\nplaintext-\\ninput", "black"), + Topic("count-\\nstore-\\nrepartition", "black"), + Topic("count-\\ntopic", "black"), + Topic("windowed-\\ncount", "black") ), Set( - Store("count-\\nstore"), - Store("windowed-\\ncount-\\nstore") + Store("count-\\nstore", "black"), + Store("windowed-\\ncount-\\nstore", "black") ) ) } diff --git a/src/test/scala/eisner/LeftJoinTopologySpec.scala b/src/test/scala/eisner/LeftJoinTopologySpec.scala index 029b5d7..791ca82 100644 --- a/src/test/scala/eisner/LeftJoinTopologySpec.scala +++ b/src/test/scala/eisner/LeftJoinTopologySpec.scala @@ -8,7 +8,8 @@ final class LeftJoinTopologySpec extends BaseEisnerSpec(2) { "Sub-\\ntopology: 1", Vector( Edge("KTABLE-\\nSOURCE-\\n0000000000", "KTABLE-\\nSOURCE-\\n0000000001") - ) + ), + "lightgrey" ), SubGraph( "0", @@ -16,7 +17,8 @@ final class LeftJoinTopologySpec extends BaseEisnerSpec(2) { Vector( Edge("KSTREAM-\\nSOURCE-\\n0000000002", "KSTREAM-\\nLEFTJOIN-\\n0000000003"), Edge("KSTREAM-\\nLEFTJOIN-\\n0000000003", "KSTREAM-\\nSINK-\\n0000000004") - ) + ), + "lightgrey" ) ), Vector( @@ -26,12 +28,12 @@ final class LeftJoinTopologySpec extends BaseEisnerSpec(2) { Edge("KTABLE-\\nSOURCE-\\n0000000001", "tax-\\ncodes-\\nstore") ), Set( - Topic("skus"), - Topic("skus-\\nwith-\\ntaxcode"), - Topic("taxcodes") + Topic("skus", "black"), + Topic("skus-\\nwith-\\ntaxcode", "black"), + Topic("taxcodes", "black") ), Set( - Store("tax-\\ncodes-\\nstore") + Store("tax-\\ncodes-\\nstore", "black") ) ) } diff --git a/src/test/scala/eisner/MoreComplexTopologySpec.scala b/src/test/scala/eisner/MoreComplexTopologySpec.scala index 61670d4..807a4f2 100644 --- a/src/test/scala/eisner/MoreComplexTopologySpec.scala +++ b/src/test/scala/eisner/MoreComplexTopologySpec.scala @@ -10,7 +10,8 @@ final class MoreComplexTopologySpec extends BaseEisnerSpec(4) { Edge("KSTREAM-\\nSOURCE-\\n0000000049", "KSTREAM-\\nREDUCE-\\n0000000046"), Edge("KSTREAM-\\nREDUCE-\\n0000000046", "KTABLE-\\nTOSTREAM-\\n0000000050"), Edge("KTABLE-\\nTOSTREAM-\\n0000000050", "KSTREAM-\\nSINK-\\n0000000051") - ) + ), + "lightgrey" ), SubGraph( "3", @@ -37,7 +38,8 @@ final class MoreComplexTopologySpec extends BaseEisnerSpec(4) { Edge("KSTREAM-\\nSOURCE-\\n0000000013", "KSTREAM-\\nREDUCE-\\n0000000010"), Edge("KSTREAM-\\nSOURCE-\\n0000000018", "KSTREAM-\\nREDUCE-\\n0000000015"), Edge("KSTREAM-\\nSOURCE-\\n0000000029", "KSTREAM-\\nREDUCE-\\n0000000026") - ) + ), + "lightgrey" ), SubGraph( "2", @@ -47,7 +49,8 @@ final class MoreComplexTopologySpec extends BaseEisnerSpec(4) { Edge("KSTREAM-\\nFLATMAP-\\n0000000005", "KSTREAM-\\nFILTER-\\n0000000038"), Edge("KSTREAM-\\nFLATMAP-\\n0000000005", "KSTREAM-\\nSINK-\\n0000000006"), Edge("KSTREAM-\\nFILTER-\\n0000000038", "KSTREAM-\\nSINK-\\n0000000037") - ) + ), + "lightgrey" ), SubGraph( "1", @@ -58,7 +61,8 @@ final class MoreComplexTopologySpec extends BaseEisnerSpec(4) { Edge("KSTREAM-\\nFLATMAP-\\n0000000003", "KSTREAM-\\nFILTER-\\n0000000032"), Edge("KSTREAM-\\nFILTER-\\n0000000017", "KSTREAM-\\nSINK-\\n0000000016"), Edge("KSTREAM-\\nFILTER-\\n0000000032", "KSTREAM-\\nSINK-\\n0000000031") - ) + ), + "lightgrey" ), SubGraph( "0", @@ -69,7 +73,8 @@ final class MoreComplexTopologySpec extends BaseEisnerSpec(4) { Edge("KSTREAM-\\nFLATMAP-\\n0000000001", "KSTREAM-\\nFILTER-\\n0000000020"), Edge("KSTREAM-\\nFILTER-\\n0000000012", "KSTREAM-\\nSINK-\\n0000000011"), Edge("KSTREAM-\\nFILTER-\\n0000000020", "KSTREAM-\\nSINK-\\n0000000019") - ) + ), + "lightgrey" ) ), Vector( @@ -101,24 +106,24 @@ final class MoreComplexTopologySpec extends BaseEisnerSpec(4) { Edge("KSTREAM-\\nSINK-\\n0000000051", "snkItemsTopic") ), Set( - Topic("KSTREAM-\\nFLATMAP-\\n0000000003-\\nrepartition"), - Topic("KSTREAM-\\nFLATMAP-\\n0000000005-\\nrepartition"), - Topic("KSTREAM-\\nREDUCE-\\nSTATE-\\nSTORE-\\n0000000025-\\nrepartition"), - Topic("KSTREAM-\\nREDUCE-\\nSTATE-\\nSTORE-\\n0000000014-\\nrepartition"), - Topic("tblDeptTopic"), - Topic("srcFeeTopic"), - Topic("srcDeptTopic"), - Topic("KSTREAM-\\nREDUCE-\\nSTATE-\\nSTORE-\\n0000000045-\\nrepartition"), - Topic("KSTREAM-\\nREDUCE-\\nSTATE-\\nSTORE-\\n0000000009-\\nrepartition"), - Topic("snkItemsTopic"), - Topic("KSTREAM-\\nFLATMAP-\\n0000000001-\\nrepartition"), - Topic("srcItemsTopic") + Topic("KSTREAM-\\nFLATMAP-\\n0000000003-\\nrepartition", "black"), + Topic("KSTREAM-\\nFLATMAP-\\n0000000005-\\nrepartition", "black"), + Topic("KSTREAM-\\nREDUCE-\\nSTATE-\\nSTORE-\\n0000000025-\\nrepartition", "black"), + Topic("KSTREAM-\\nREDUCE-\\nSTATE-\\nSTORE-\\n0000000014-\\nrepartition", "black"), + Topic("tblDeptTopic", "black"), + Topic("srcFeeTopic", "black"), + Topic("srcDeptTopic", "black"), + Topic("KSTREAM-\\nREDUCE-\\nSTATE-\\nSTORE-\\n0000000045-\\nrepartition", "black"), + Topic("KSTREAM-\\nREDUCE-\\nSTATE-\\nSTORE-\\n0000000009-\\nrepartition", "black"), + Topic("snkItemsTopic", "black"), + Topic("KSTREAM-\\nFLATMAP-\\n0000000001-\\nrepartition", "black"), + Topic("srcItemsTopic", "black") ), Set( - Store("KSTREAM-\\nREDUCE-\\nSTATE-\\nSTORE-\\n0000000014"), - Store("KSTREAM-\\nREDUCE-\\nSTATE-\\nSTORE-\\n0000000009"), - Store("KSTREAM-\\nREDUCE-\\nSTATE-\\nSTORE-\\n0000000025"), - Store("KSTREAM-\\nREDUCE-\\nSTATE-\\nSTORE-\\n0000000045") + Store("KSTREAM-\\nREDUCE-\\nSTATE-\\nSTORE-\\n0000000014", "black"), + Store("KSTREAM-\\nREDUCE-\\nSTATE-\\nSTORE-\\n0000000009", "black"), + Store("KSTREAM-\\nREDUCE-\\nSTATE-\\nSTORE-\\n0000000025", "black"), + Store("KSTREAM-\\nREDUCE-\\nSTATE-\\nSTORE-\\n0000000045", "black") ) ) } diff --git a/src/test/scala/eisner/SimpleTopologySpec.scala b/src/test/scala/eisner/SimpleTopologySpec.scala index 3b799c8..daf42b6 100644 --- a/src/test/scala/eisner/SimpleTopologySpec.scala +++ b/src/test/scala/eisner/SimpleTopologySpec.scala @@ -10,7 +10,8 @@ final class SimpleTopologySpec extends BaseEisnerSpec(1) { Edge("KSTREAM-\\nSOURCE-\\n0000000006", "KSTREAM-\\nAGGREGATE-\\n0000000003"), Edge("KSTREAM-\\nAGGREGATE-\\n0000000003", "KTABLE-\\nTOSTREAM-\\n0000000007"), Edge("KTABLE-\\nTOSTREAM-\\n0000000007", "KSTREAM-\\nSINK-\\n0000000008") - ) + ), + "lightgrey" ), SubGraph( "0", @@ -20,7 +21,8 @@ final class SimpleTopologySpec extends BaseEisnerSpec(1) { Edge("KSTREAM-\\nTRANSFORM-\\n0000000001", "KSTREAM-\\nKEY-\\nSELECT-\\n0000000002"), Edge("KSTREAM-\\nKEY-\\nSELECT-\\n0000000002", "KSTREAM-\\nFILTER-\\n0000000005"), Edge("KSTREAM-\\nFILTER-\\n0000000005", "KSTREAM-\\nSINK-\\n0000000004") - ) + ), + "lightgrey" ) ), Vector( @@ -32,13 +34,13 @@ final class SimpleTopologySpec extends BaseEisnerSpec(1) { Edge("KSTREAM-\\nSINK-\\n0000000008", "streams-\\ncount-\\nresolved") ), Set( - Topic("conversation-\\nmeta"), - Topic("count-\\nresolved-\\nrepartition"), - Topic("streams-\\ncount-\\nresolved") + Topic("conversation-\\nmeta", "black"), + Topic("count-\\nresolved-\\nrepartition", "black"), + Topic("streams-\\ncount-\\nresolved", "black") ), Set( - Store("conversation-\\nmeta-\\nstate"), - Store("count-\\nresolved") + Store("conversation-\\nmeta-\\nstate", "black"), + Store("count-\\nresolved", "black") ) ) }