From cf510ddf1abaa42dc4b90f3ac80a55e82da6eac3 Mon Sep 17 00:00:00 2001 From: Jonathan Shook Date: Fri, 29 Sep 2023 02:01:28 -0500 Subject: [PATCH] component scaffolding --- .../api/config/standard/TestComponent.java | 32 +++++--- .../NBBaseComponent.java | 33 +++++++-- .../config => components}/NBComponent.java | 11 ++- .../components/NBComponentSubScope.java | 30 ++++++++ .../components/NBComponentTraversal.java | 74 +++++++++++++++++++ .../components/NBComponentViews.java | 36 +++++++++ .../api/labels/NBLabelsRenderingTest.java | 44 +++++++++++ .../components/NBComponentLifecycleTest.java | 41 ++++++++++ .../components/NBComponentTraversalTest.java | 51 +++++++++++++ .../components/NBComponentViewsTest.java | 37 ++++++++++ 10 files changed, 373 insertions(+), 16 deletions(-) rename nb-api/src/main/java/io/nosqlbench/{api/config/standard => components}/NBBaseComponent.java (57%) rename nb-api/src/main/java/io/nosqlbench/{api/config => components}/NBComponent.java (88%) create mode 100644 nb-api/src/main/java/io/nosqlbench/components/NBComponentSubScope.java create mode 100644 nb-api/src/main/java/io/nosqlbench/components/NBComponentTraversal.java create mode 100644 nb-api/src/main/java/io/nosqlbench/components/NBComponentViews.java create mode 100644 nb-api/src/test/java/io/nosqlbench/api/labels/NBLabelsRenderingTest.java create mode 100644 nb-api/src/test/java/io/nosqlbench/components/NBComponentLifecycleTest.java create mode 100644 nb-api/src/test/java/io/nosqlbench/components/NBComponentTraversalTest.java create mode 100644 nb-api/src/test/java/io/nosqlbench/components/NBComponentViewsTest.java diff --git a/nb-api/src/main/java/io/nosqlbench/api/config/standard/TestComponent.java b/nb-api/src/main/java/io/nosqlbench/api/config/standard/TestComponent.java index 7cdd570fb..39ab1b253 100644 --- a/nb-api/src/main/java/io/nosqlbench/api/config/standard/TestComponent.java +++ b/nb-api/src/main/java/io/nosqlbench/api/config/standard/TestComponent.java @@ -16,24 +16,38 @@ package io.nosqlbench.api.config.standard; -import io.nosqlbench.api.config.NBComponent; import io.nosqlbench.api.labels.NBLabels; +import io.nosqlbench.components.NBBaseComponent; +import io.nosqlbench.components.NBComponent; -public class TestComponent implements NBComponent { +import java.util.Arrays; + +public class TestComponent extends NBBaseComponent { public static final NBComponent INSTANCE = new TestComponent(); - private final NBLabels labels; public TestComponent(String... labels) { - this.labels = NBLabels.forKV((Object[]) labels); + super(null,NBLabels.forKV((Object[]) labels)); } - @Override - public NBComponent getParent() { - return this; + + public TestComponent(NBComponent parent, String... labels) { + super(parent, NBLabels.forKV((Object[]) labels)); } @Override - public NBLabels getLabels() { - return labels; + public String toString() { + return getLabels().linearizeAsMetrics() + " ("+this.getClass().getSimpleName()+")"; + } + + @Override + public NBComponent attach(NBComponent... children) { + System.out.println("attaching children:" + Arrays.toString(children)); + return super.attach(children); + } + + @Override + public NBComponent detach(NBComponent... children) { + System.out.println("detaching children:" + Arrays.toString(children)); + return super.detach(children); } } diff --git a/nb-api/src/main/java/io/nosqlbench/api/config/standard/NBBaseComponent.java b/nb-api/src/main/java/io/nosqlbench/components/NBBaseComponent.java similarity index 57% rename from nb-api/src/main/java/io/nosqlbench/api/config/standard/NBBaseComponent.java rename to nb-api/src/main/java/io/nosqlbench/components/NBBaseComponent.java index 7c4c8e6a5..a147ff437 100644 --- a/nb-api/src/main/java/io/nosqlbench/api/config/standard/NBBaseComponent.java +++ b/nb-api/src/main/java/io/nosqlbench/components/NBBaseComponent.java @@ -14,18 +14,21 @@ * limitations under the License. */ -package io.nosqlbench.api.config.standard; +package io.nosqlbench.components; -import io.nosqlbench.api.config.NBComponent; import io.nosqlbench.api.labels.NBLabels; +import java.util.*; + public class NBBaseComponent implements NBComponent { private final NBComponent parent; + private final List children = new ArrayList<>(); private final NBLabels labels; - public NBBaseComponent(NBComponent parentComponent, NBLabels compomentSpecificLabelsOnly) { + public NBBaseComponent(NBComponent parentComponent, NBLabels componentSpecificLabelsOnly) { + this.labels = componentSpecificLabelsOnly; this.parent = parentComponent; - this.labels = compomentSpecificLabelsOnly; + if (this.parent!=null) { parentComponent.attach(this);} } @Override public NBComponent getParent() { @@ -33,7 +36,25 @@ public class NBBaseComponent implements NBComponent { } @Override - public NBLabels getLabels() { - return this.parent.getLabels().and(labels); + public NBComponent attach(NBComponent... children) { + this.children.addAll(Arrays.asList(children)); + return this; } + + @Override + public NBComponent detach(NBComponent... children) { + this.children.removeAll(Arrays.asList(children)); + return this; + } + + @Override + public List getChildren() { + return children; + } + + @Override + public NBLabels getLabels() { + return (this.parent==null) ? labels : this.parent.getLabels().and(labels); + } + } diff --git a/nb-api/src/main/java/io/nosqlbench/api/config/NBComponent.java b/nb-api/src/main/java/io/nosqlbench/components/NBComponent.java similarity index 88% rename from nb-api/src/main/java/io/nosqlbench/api/config/NBComponent.java rename to nb-api/src/main/java/io/nosqlbench/components/NBComponent.java index 3c1cdbf6e..65f895b84 100644 --- a/nb-api/src/main/java/io/nosqlbench/api/config/NBComponent.java +++ b/nb-api/src/main/java/io/nosqlbench/components/NBComponent.java @@ -14,10 +14,12 @@ * limitations under the License. */ -package io.nosqlbench.api.config; +package io.nosqlbench.components; import io.nosqlbench.api.labels.NBLabeledElement; +import java.util.List; + /** * A Component is a functional element of the NoSQLBench runtime which is: *
    @@ -34,4 +36,11 @@ import io.nosqlbench.api.labels.NBLabeledElement; public interface NBComponent extends NBLabeledElement { NBComponent getParent(); + + NBComponent attach(NBComponent... children); + + NBComponent detach(NBComponent... children); + + List getChildren(); + } diff --git a/nb-api/src/main/java/io/nosqlbench/components/NBComponentSubScope.java b/nb-api/src/main/java/io/nosqlbench/components/NBComponentSubScope.java new file mode 100644 index 000000000..b00a31258 --- /dev/null +++ b/nb-api/src/main/java/io/nosqlbench/components/NBComponentSubScope.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.components; + +public class NBComponentSubScope implements AutoCloseable { + + private final NBComponent component; + + public NBComponentSubScope(NBComponent component) { + this.component = component; + } + @Override + public void close() throws RuntimeException { + component.getParent().detach(component); + } +} diff --git a/nb-api/src/main/java/io/nosqlbench/components/NBComponentTraversal.java b/nb-api/src/main/java/io/nosqlbench/components/NBComponentTraversal.java new file mode 100644 index 000000000..c95c04f3c --- /dev/null +++ b/nb-api/src/main/java/io/nosqlbench/components/NBComponentTraversal.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2023 nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.components; + +import java.util.Iterator; +import java.util.LinkedList; + +public class NBComponentTraversal { + + public static Iterator traverseDepth(NBComponent component) { + return new iterDepthFirst(component); + } + + public static Iterator traverseBreadth(NBComponent component) { + return new IterBreadthFirst(component); + } + + private static final class iterDepthFirst implements Iterator { + + private final LinkedList traversal = new LinkedList<>(); + public iterDepthFirst(NBComponent comp) { + traversal.add(comp); + } + + @Override + public boolean hasNext() { + return (!traversal.isEmpty()); + } + + @Override + public NBComponent next() { + NBComponent next = traversal.remove(); + for (NBComponent child : next.getChildren().reversed()) { + traversal.addFirst(child); + } + return next; + } + } + + private static final class IterBreadthFirst implements Iterator { + private final LinkedList traversal = new LinkedList<>(); + + public IterBreadthFirst(NBComponent component) { + traversal.addFirst(component); + } + + @Override + public boolean hasNext() { + return (!traversal.isEmpty()); + } + + @Override + public NBComponent next() { + NBComponent next = traversal.removeFirst(); + traversal.addAll(next.getChildren()); + return next; + } + } + +} diff --git a/nb-api/src/main/java/io/nosqlbench/components/NBComponentViews.java b/nb-api/src/main/java/io/nosqlbench/components/NBComponentViews.java new file mode 100644 index 000000000..63b7a53f3 --- /dev/null +++ b/nb-api/src/main/java/io/nosqlbench/components/NBComponentViews.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.components; + +import java.util.function.Function; + +public class NBComponentViews { + public static String treeView(NBComponent node) { + return treeView(new StringBuilder(), node, 0, Object::toString); + } + + public static String treeView(NBComponent node, Function representer) { + return treeView(new StringBuilder(), node, 0, representer); + } + private static String treeView(StringBuilder sb, NBComponent node, int level, Function stringify) { + sb.append(" ".repeat(level)).append(stringify.apply(node)).append("\n"); + for (NBComponent child : node.getChildren()) { + treeView(sb,child,level+1,stringify); + } + return sb.toString(); + } +} diff --git a/nb-api/src/test/java/io/nosqlbench/api/labels/NBLabelsRenderingTest.java b/nb-api/src/test/java/io/nosqlbench/api/labels/NBLabelsRenderingTest.java new file mode 100644 index 000000000..34c9af8a2 --- /dev/null +++ b/nb-api/src/test/java/io/nosqlbench/api/labels/NBLabelsRenderingTest.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023 nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.api.labels; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +class NBLabelsRenderingTest { + + @Test + public void testLinearizeDot() { + var l1 = NBLabels.forKV("a","b","c","d","e","f"); + String al1 = l1.linearize("a"); + assertThat(al1).isEqualTo("b{c=\"d\",e=\"f\"}"); + String al2 = l1.linearizeValues(','); + assertThat(al2).isEqualTo("b,d,f"); + String al3 = l1.linearizeValues("a","c"); + assertThat(al3).isEqualTo("b.d"); + } + + @Test + public void testLinearizeOpenMetricsFormat() { + var l1 = NBLabels.forKV("a","b","c","d","e","f"); + String oml1 = l1.linearizeAsMetrics(); + assertThat(oml1).isEqualTo("{a:\"b\",c:\"d\",e:\"f\"}"); + } + +} diff --git a/nb-api/src/test/java/io/nosqlbench/components/NBComponentLifecycleTest.java b/nb-api/src/test/java/io/nosqlbench/components/NBComponentLifecycleTest.java new file mode 100644 index 000000000..0bc4e3d13 --- /dev/null +++ b/nb-api/src/test/java/io/nosqlbench/components/NBComponentLifecycleTest.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2023 nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.components; + +import io.nosqlbench.api.config.standard.TestComponent; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class NBComponentLifecycleTest { + + @Test + public void testBasicLifecycleHooks() { + TestComponent root = new TestComponent("role", "root"); + TestComponent node1 = new TestComponent(root, "node1", "node1"); + TestComponent node2 = new TestComponent(root, "node2", "node2"); + TestComponent node3 = new TestComponent(root, "node3", "node3"); + + try (NBComponentSubScope scope = new NBComponentSubScope(node1)) { + System.out.println("node1 active"); + } + + System.out.print("node1 inactive"); + + } + +} diff --git a/nb-api/src/test/java/io/nosqlbench/components/NBComponentTraversalTest.java b/nb-api/src/test/java/io/nosqlbench/components/NBComponentTraversalTest.java new file mode 100644 index 000000000..a203aca1a --- /dev/null +++ b/nb-api/src/test/java/io/nosqlbench/components/NBComponentTraversalTest.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2023 nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.components; + +import io.nosqlbench.api.config.standard.TestComponent; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.Iterator; + +import static org.assertj.core.api.Assertions.assertThat; + +class NBComponentTraversalTest { + + private final static TestComponent a = new TestComponent("name_a","a"); + private final static TestComponent sub1 = new TestComponent(a, "name_1", "1"); + private final static TestComponent sub2 = new TestComponent(a, "name_2", "2"); + private final static TestComponent dotX = new TestComponent(sub1, "name_X", "X"); + private final static TestComponent dotY = new TestComponent(sub1, "name_Y", "Y"); + + + @Test + public void testDepthFirstTraversal() { + Iterator byDepth = NBComponentTraversal.traverseDepth(a); + ArrayList taller = new ArrayList<>(); + byDepth.forEachRemaining(taller::add); + assertThat(taller).containsExactly(a,sub1,dotX,dotY,sub2); + } + @Test + public void testBreadthFirstTraversal() { + Iterator byBreadth = NBComponentTraversal.traverseBreadth(a); + ArrayList wider = new ArrayList<>(); + byBreadth.forEachRemaining(wider::add); + assertThat(wider).containsExactly(a,sub1,sub2,dotX,dotY); + } + +} diff --git a/nb-api/src/test/java/io/nosqlbench/components/NBComponentViewsTest.java b/nb-api/src/test/java/io/nosqlbench/components/NBComponentViewsTest.java new file mode 100644 index 000000000..9145c9578 --- /dev/null +++ b/nb-api/src/test/java/io/nosqlbench/components/NBComponentViewsTest.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.components; + +import io.nosqlbench.api.config.standard.TestComponent; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class NBComponentViewsTest { + @Test + public void testBasicTreeView() { + var root = new TestComponent("a", "b") + .attach(new TestComponent("c", "d") + .attach(new TestComponent("U", "V")) + .attach(new TestComponent("Y","Z"))) + .attach(new TestComponent("e", "f")); + System.out.println(NBComponentViews.treeView(root)); + + System.out.println(NBComponentViews.treeView(root, c -> c.getLabels().asMap().keySet().stream().findFirst().orElseThrow())); + } + +}