From 93109a901deea9aa3e85038dc50fdbb9b32f8c9d Mon Sep 17 00:00:00 2001 From: Henning Baldersheim Date: Wed, 25 Jan 2023 20:24:26 +0100 Subject: Stack => Deque and gc unused ConfigFileFormat --- .../com/yahoo/vespa/config/ConfigFileFormat.java | 228 -------------- .../yahoo/vespa/config/ConfigPayloadApplier.java | 60 ++-- .../config/protocol/SlimeTraceSerializer.java | 5 +- .../vespa/config/ConfigFileFormatterTest.java | 338 --------------------- 4 files changed, 31 insertions(+), 600 deletions(-) delete mode 100644 config/src/main/java/com/yahoo/vespa/config/ConfigFileFormat.java delete mode 100644 config/src/test/java/com/yahoo/vespa/config/ConfigFileFormatterTest.java (limited to 'config/src') diff --git a/config/src/main/java/com/yahoo/vespa/config/ConfigFileFormat.java b/config/src/main/java/com/yahoo/vespa/config/ConfigFileFormat.java deleted file mode 100644 index 16a3ef3371d..00000000000 --- a/config/src/main/java/com/yahoo/vespa/config/ConfigFileFormat.java +++ /dev/null @@ -1,228 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config; - -import com.yahoo.config.codegen.CNode; -import com.yahoo.config.codegen.InnerCNode; -import com.yahoo.config.codegen.LeafCNode; -import com.yahoo.slime.*; -import com.yahoo.text.Utf8; -import com.yahoo.vespa.config.util.ConfigUtils; - -import java.io.*; -import java.util.Stack; - -/** - * @author Ulf Lilleengen - */ -public class ConfigFileFormat implements SlimeFormat, ObjectTraverser { - - private final InnerCNode root; - private DataOutputStream out = null; - private Stack nodeStack; - - public ConfigFileFormat(InnerCNode root) { - this.root = root; - this.nodeStack = new Stack<>(); - } - - private void printPrefix() throws IOException { - for (Node node : nodeStack) { - CNode cnode = node.node; - if (cnode != root) { - encodeString(cnode.getName()); - if (cnode.isArray) { - encodeString("[" + node.arrayIndex + "]"); - if (!(cnode instanceof LeafCNode)) { - encodeString("."); - } - } else if (cnode.isMap) { - encodeString("{\"" + node.mapKey + "\"}"); - if (!(cnode instanceof LeafCNode)) { - encodeString("."); - } - } else if (cnode instanceof LeafCNode) { - encodeString(""); - } else { - encodeString("."); - } - } - } - encodeString(" "); - } - - private void encode(Inspector inspector, CNode node) throws IOException { - switch (inspector.type()) { - case BOOL: - encodeValue(String.valueOf(inspector.asBool()), (LeafCNode) node); - return; - case LONG: - encodeValue(String.valueOf(inspector.asLong()), (LeafCNode) node); - return; - case DOUBLE: - encodeValue(String.valueOf(inspector.asDouble()), (LeafCNode) node); - return; - case STRING: - encodeValue(inspector.asString(), (LeafCNode) node); - return; - case ARRAY: - encodeArray(inspector, node); - return; - case OBJECT: - if (node.isMap) { - encodeMap(inspector, node); - } else { - encodeObject(inspector, node); - } - return; - case NIX: - case DATA: - throw new IllegalArgumentException("Illegal config format supplied. Unknown type for field '" + node.getName() + "'"); - } - throw new RuntimeException("Should not be reached"); - } - - private void encodeMap(Inspector inspector, final CNode node) { - inspector.traverse(new ObjectTraverser() { - @Override - public void field(String name, Inspector inspector) { - try { - nodeStack.push(new Node(node, -1, name)); - if (inspector.type().equals(Type.OBJECT)) { - encodeObject(inspector, node); - } else { - encode(inspector, node); - } - nodeStack.pop(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - }); - } - - private void encodeArray(Inspector inspector, final CNode node) { - inspector.traverse(new ArrayTraverser() { - @Override - public void entry(int idx, Inspector inspector) { - try { - nodeStack.push(new Node(node, idx, "")); - encode(inspector, node); - nodeStack.pop(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - }); - - } - - private void encodeObject(Inspector inspector, CNode node) { - if (!node.isArray && !node.isMap) { - nodeStack.push(new Node(node)); - inspector.traverse(this); - nodeStack.pop(); - } else { - inspector.traverse(this); - } - } - - private void encodeValue(String value, LeafCNode node) throws IOException { - printPrefix(); - try { - if (node instanceof LeafCNode.StringLeaf) { - encodeStringQuoted(value); - } else if (node instanceof LeafCNode.IntegerLeaf) { - //Integer.parseInt(value); - encodeString(value); - } else if (node instanceof LeafCNode.LongLeaf) { - //Long.parseLong(value); - encodeString(value); - } else if (node instanceof LeafCNode.DoubleLeaf) { - //Double.parseDouble(value); - encodeString(value); - } else if (node instanceof LeafCNode.BooleanLeaf) { - encodeString(String.valueOf(Boolean.parseBoolean(value))); - } else if (node instanceof LeafCNode.EnumLeaf) { - // LeafCNode.EnumLeaf enumNode = (LeafCNode.EnumLeaf) node; - // TODO: Reenable this when we can return illegal config id. - // checkLegalEnumValue(enumNode, value); - encodeString(value); - } else { - encodeStringQuoted(value); - } - encodeString("\n"); - } catch (Exception e) { - throw new IllegalArgumentException("Unable to serialize field '" + node.getFullName() + "': ", e); - } - } - - private void checkLegalEnumValue(LeafCNode.EnumLeaf enumNode, String value) { - boolean found = false; - for (String legalVal : enumNode.getLegalValues()) { - if (legalVal.equals(value)) { - found = true; - } - } - if (!found) - throw new IllegalArgumentException("Illegal enum value '" + value + "'"); - } - - private void encodeStringQuoted(String s) throws IOException { - encodeString("\"" + escapeString(s) + "\""); - } - - private String escapeString(String s) { - return ConfigUtils.escapeConfigFormatValue(s); - } - - private void encodeString(String s) throws IOException { - out.write(Utf8.toBytes(s)); - } - - @Override - public void encode(OutputStream os, Slime slime) throws IOException { - encode(os, slime.get()); - } - - private void encode(OutputStream os, Inspector inspector) throws IOException { - this.out = new DataOutputStream(os); - this.nodeStack = new Stack<>(); - nodeStack.push(new Node(root)); - encode(inspector, root); - } - - @Override - public void field(String fieldName, Inspector inspector) { - try { - Node parent = nodeStack.peek(); - CNode child = parent.node.getChild(fieldName); - if (child == null) { - return; // Skip this field to optimistic - } - if (!child.isArray && !child.isMap && child instanceof LeafCNode) { - nodeStack.push(new Node(child)); - encode(inspector, child); - nodeStack.pop(); - } else { - encode(inspector, child); - } - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - private class Node { - final int arrayIndex; - final String mapKey; - final CNode node; - Node(CNode node, int arrayIndex, String mapKey) { - this.node = node; - this.arrayIndex = arrayIndex; - this.mapKey = mapKey; - } - - Node(CNode node) { - this(node, -1, ""); - } - } -} diff --git a/config/src/main/java/com/yahoo/vespa/config/ConfigPayloadApplier.java b/config/src/main/java/com/yahoo/vespa/config/ConfigPayloadApplier.java index 3705c167960..e86b13b2c98 100644 --- a/config/src/main/java/com/yahoo/vespa/config/ConfigPayloadApplier.java +++ b/config/src/main/java/com/yahoo/vespa/config/ConfigPayloadApplier.java @@ -8,7 +8,6 @@ import com.yahoo.config.ModelReference; import com.yahoo.config.UrlReference; import com.yahoo.slime.ArrayTraverser; import com.yahoo.slime.Inspector; -import com.yahoo.slime.ObjectTraverser; import com.yahoo.slime.Type; import java.io.File; import java.lang.reflect.Constructor; @@ -17,11 +16,12 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.nio.file.Path; +import java.util.ArrayDeque; +import java.util.Deque; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; -import java.util.Stack; import java.util.logging.Logger; import static java.util.logging.Level.INFO; @@ -42,7 +42,7 @@ public class ConfigPayloadApplier { private final ConfigInstance.Builder rootBuilder; private final ConfigTransformer.PathAcquirer pathAcquirer; private final UrlDownloader urlDownloader; - private final Stack stack = new Stack<>(); + private final Deque stack = new ArrayDeque<>(); public ConfigPayloadApplier(T builder) { this(builder, new IdentityPathAcquirer(), null); @@ -67,27 +67,17 @@ public class ConfigPayloadApplier { private void handleValue(Inspector inspector) { switch (inspector.type()) { - case NIX: - case BOOL: - case LONG: - case DOUBLE: - case STRING: - case DATA: - handleLeafValue(inspector); - break; - case ARRAY: - handleARRAY(inspector); - break; - case OBJECT: - handleOBJECT(inspector); - break; - default: + case NIX, BOOL, LONG, DOUBLE, STRING, DATA -> handleLeafValue(inspector); + case ARRAY -> handleARRAY(inspector); + case OBJECT -> handleOBJECT(inspector); + default -> { assert false : "Should not be reached"; + } } } private void handleARRAY(Inspector inspector) { - inspector.traverse((ArrayTraverser)(int index, Inspector value) -> handleArrayEntry(index, value)); + inspector.traverse((ArrayTraverser) this::handleArrayEntry); } private void handleArrayEntry(int idx, Inspector inspector) { @@ -108,11 +98,11 @@ public class ConfigPayloadApplier { } private void handleOBJECT(Inspector inspector) { - inspector.traverse((String name, Inspector value) -> handleObjectEntry(name, value)); + inspector.traverse(this::handleObjectEntry); NamedBuilder builder = stack.pop(); // Need to set e.g struct(Struct.Builder) here - if ( ! stack.empty()) { + if ( ! stack.isEmpty()) { try { invokeSetter(stack.peek().builder, builder.peekName(), builder.builder); } catch (Exception e) { @@ -165,7 +155,7 @@ public class ConfigPayloadApplier { throw new RuntimeException("Missing map builder (this should never happen): " + stack.peek()); setMapLeafValue(name, builder.builder()); stack.push(builder); - inspector.traverse((ObjectTraverser) (key, value) -> handleObjectEntry(key, value)); + inspector.traverse(this::handleObjectEntry); stack.pop(); } @@ -296,18 +286,24 @@ public class ConfigPayloadApplier { private Object getValueFromInspector(Inspector inspector) { switch (inspector.type()) { - case STRING: + case STRING -> { return inspector.asString(); - case LONG: + } + case LONG -> { return String.valueOf(inspector.asLong()); - case DOUBLE: + } + case DOUBLE -> { return String.valueOf(inspector.asDouble()); - case NIX: + } + case NIX -> { return null; - case BOOL: + } + case BOOL -> { return String.valueOf(inspector.asBool()); - case DATA: + } + case DATA -> { return String.valueOf(inspector.asData()); + } } throw new IllegalArgumentException("Unhandled type " + inspector.type()); } @@ -372,7 +368,7 @@ public class ConfigPayloadApplier { return name.substring(0, 1).toUpperCase() + name.substring(1); } - private Constructor lookupBuilderForStruct(String structName, String name, Class currentClass) { + private Constructor lookupBuilderForStruct(String structName, Class currentClass) { String currentClassName = currentClass.getName(); Class structClass = getInnerClass(currentClass, currentClassName + "$" + structName); if (structClass == null) { @@ -420,7 +416,7 @@ public class ConfigPayloadApplier { String key = constructorCacheKey(structName, name, currentClass); Constructor constructor = constructorCache.get(key); if (constructor == null) { - constructor = lookupBuilderForStruct(structName, name, currentClass); + constructor = lookupBuilderForStruct(structName, currentClass); if (constructor == null) return null; constructorCache.put(key, constructor); } @@ -437,7 +433,7 @@ public class ConfigPayloadApplier { private static class NamedBuilder { private final ConfigBuilder builder; - private final Stack names = new Stack<>(); // if empty, the builder is the root builder + private final Deque names = new ArrayDeque<>(); // if empty, the builder is the root builder NamedBuilder(ConfigBuilder builder) { this.builder = builder; @@ -456,7 +452,7 @@ public class ConfigPayloadApplier { return names.peek(); } - Stack nameStack() { + Deque nameStack() { return names; } diff --git a/config/src/main/java/com/yahoo/vespa/config/protocol/SlimeTraceSerializer.java b/config/src/main/java/com/yahoo/vespa/config/protocol/SlimeTraceSerializer.java index 875033f1ffa..5193ecddc82 100644 --- a/config/src/main/java/com/yahoo/vespa/config/protocol/SlimeTraceSerializer.java +++ b/config/src/main/java/com/yahoo/vespa/config/protocol/SlimeTraceSerializer.java @@ -5,8 +5,9 @@ import com.yahoo.slime.Cursor; import com.yahoo.yolean.trace.TraceNode; import com.yahoo.yolean.trace.TraceVisitor; +import java.util.ArrayDeque; +import java.util.Deque; import java.util.Iterator; -import java.util.Stack; /** * Serialize a {@link TraceNode} to {@link com.yahoo.slime.Slime}. @@ -17,7 +18,7 @@ public class SlimeTraceSerializer extends TraceVisitor { static final String TIMESTAMP = "timestamp"; static final String PAYLOAD = "payload"; static final String CHILDREN = "children"; - final Stack cursors = new Stack<>(); + final Deque cursors = new ArrayDeque<>(); public SlimeTraceSerializer(Cursor cursor) { cursors.push(cursor); diff --git a/config/src/test/java/com/yahoo/vespa/config/ConfigFileFormatterTest.java b/config/src/test/java/com/yahoo/vespa/config/ConfigFileFormatterTest.java deleted file mode 100644 index ab07b669bd0..00000000000 --- a/config/src/test/java/com/yahoo/vespa/config/ConfigFileFormatterTest.java +++ /dev/null @@ -1,338 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config; - -import com.yahoo.foo.ArraytypesConfig; -import com.yahoo.foo.SimpletypesConfig; -import com.yahoo.foo.StructtypesConfig; -import com.yahoo.config.codegen.DefParser; -import com.yahoo.config.codegen.InnerCNode; -import com.yahoo.foo.MaptypesConfig; -import com.yahoo.slime.Cursor; -import com.yahoo.slime.Slime; -import com.yahoo.text.StringUtilities; -import com.yahoo.text.Utf8; -import org.junit.Test; -import org.junit.Ignore; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.StringReader; -import java.nio.charset.StandardCharsets; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * @author Ulf Lilleengen - */ -public class ConfigFileFormatterTest { - - private final String expected_simpletypes = "stringval \"foo\"\n" + - "intval 324234\n" + - "longval 324\n" + - "doubleval 3.455\n" + - "enumval VAL2\n" + - "boolval true\n"; - - @Test - public void require_that_basic_formatting_is_correct() throws IOException { - Slime slime = new Slime(); - Cursor root = slime.setObject(); - root.setString("stringval", "foo"); - root.setString("intval", "324234"); - root.setString("longval", "324"); - root.setString("doubleval", "3.455"); - root.setString("enumval", "VAL2"); - root.setString("boolval", "true"); - - assertConfigFormat(slime, expected_simpletypes); - } - - @Test - public void require_that_basic_formatting_is_correct_with_types() throws IOException { - Slime slime = new Slime(); - Cursor root = slime.setObject(); - root.setString("stringval", "foo"); - root.setLong("intval", 324234); - root.setLong("longval", 324); - root.setDouble("doubleval", 3.455); - root.setString("enumval", "VAL2"); - root.setBool("boolval", true); - - assertConfigFormat(slime, expected_simpletypes); - } - - private void assertConfigFormat(Slime slime, String expected_simpletypes) throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - InnerCNode def = new DefParser("simpletypes", new StringReader(StringUtilities.implode(SimpletypesConfig.CONFIG_DEF_SCHEMA, "\n"))).getTree(); - new ConfigFileFormat(def).encode(baos, slime); - assertEquals(expected_simpletypes, baos.toString()); - } - - @Test - public void require_that_field_not_found_is_ignored() throws IOException { - Slime slime = new Slime(); - Cursor root = slime.setObject(); - root.setString("nosuchfield", "bar"); - InnerCNode def = new DefParser("simpletypes", new StringReader(StringUtilities.implode(SimpletypesConfig.CONFIG_DEF_SCHEMA, "\n"))).getTree(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - new ConfigFileFormat(def).encode(baos, slime); - assertTrue(baos.toString().isEmpty()); - } - - // TODO: Reenable this when we can reenable typechecking. - @Ignore - @Test(expected = IllegalArgumentException.class) - public void require_that_illegal_int_throws_exception() throws IOException { - Slime slime = new Slime(); - Cursor root = slime.setObject(); - root.setString("intval", "invalid"); - InnerCNode def = new DefParser("simpletypes", new StringReader(StringUtilities.implode(SimpletypesConfig.CONFIG_DEF_SCHEMA, "\n"))).getTree(); - new ConfigFileFormat(def).encode(new ByteArrayOutputStream(), slime); - } - - // TODO: Reenable this when we can reenable typechecking. - @Ignore - @Test(expected = IllegalArgumentException.class) - public void require_that_illegal_long_throws_exception() throws IOException { - Slime slime = new Slime(); - Cursor root = slime.setObject(); - root.setString("longval", "invalid"); - InnerCNode def = new DefParser("simpletypes", new StringReader(StringUtilities.implode(SimpletypesConfig.CONFIG_DEF_SCHEMA, "\n"))).getTree(); - new ConfigFileFormat(def).encode(new ByteArrayOutputStream(), slime); - } - - // TODO: Reenable this when we can reenable typechecking. - @Ignore - @Test(expected = IllegalArgumentException.class) - public void require_that_illegal_double_throws_exception() throws IOException { - Slime slime = new Slime(); - Cursor root = slime.setObject(); - root.setString("doubleval", "invalid"); - InnerCNode def = new DefParser("simpletypes", new StringReader(StringUtilities.implode(SimpletypesConfig.CONFIG_DEF_SCHEMA, "\n"))).getTree(); - new ConfigFileFormat(def).encode(new ByteArrayOutputStream(), slime); - } - - @Test - public void require_that_illegal_boolean_becomes_false() throws IOException { - Slime slime = new Slime(); - Cursor root = slime.setObject(); - root.setString("boolval", "invalid"); - InnerCNode def = new DefParser("simpletypes", new StringReader(StringUtilities.implode(SimpletypesConfig.CONFIG_DEF_SCHEMA, "\n"))).getTree(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - new ConfigFileFormat(def).encode(baos, slime); - assertEquals("boolval false\n", baos.toString()); - } - - // TODO: Remove this when we can reenable typechecking. - @Test - public void require_that_types_are_not_checked() throws IOException { - Slime slime = new Slime(); - Cursor root = slime.setObject(); - root.setString("enumval", "null"); - root.setString("intval", "null"); - root.setString("longval", "null"); - root.setString("boolval", "null"); - root.setString("doubleval", "null"); - InnerCNode def = new DefParser("simpletypes", new StringReader(StringUtilities.implode(SimpletypesConfig.CONFIG_DEF_SCHEMA, "\n"))).getTree(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - new ConfigFileFormat(def).encode(baos, slime); - assertEquals("enumval null\nintval null\nlongval null\nboolval false\ndoubleval null\n", - baos.toString(StandardCharsets.UTF_8)); - } - - // TODO: Reenable this when we can reenable typechecking. - @Ignore - @Test(expected = IllegalArgumentException.class) - public void require_that_illegal_enum_throws_exception() throws IOException { - Slime slime = new Slime(); - Cursor root = slime.setObject(); - root.setString("enumval", "invalid"); - InnerCNode def = new DefParser("simpletypes", new StringReader(StringUtilities.implode(SimpletypesConfig.CONFIG_DEF_SCHEMA, "\n"))).getTree(); - new ConfigFileFormat(def).encode(new ByteArrayOutputStream(), slime); - } - - @Test - public void require_that_strings_are_encoded() throws IOException { - Slime slime = new Slime(); - Cursor root = slime.setObject(); - String value = "\u7d22"; - root.setString("stringval", value); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - InnerCNode def = new DefParser("simpletypes", new StringReader(StringUtilities.implode(SimpletypesConfig.CONFIG_DEF_SCHEMA, "\n"))).getTree(); - new ConfigFileFormat(def).encode(baos, slime); - assertEquals("stringval \"" + value + "\"\n", baos.toString(StandardCharsets.UTF_8)); - } - - @Test - public void require_that_array_formatting_is_correct() throws IOException { - Slime slime = new Slime(); - Cursor root = slime.setObject(); - Cursor boolarr = root.setArray("boolarr"); - boolarr.addString("true"); - boolarr.addString("false"); - Cursor doublearr = root.setArray("doublearr"); - doublearr.addString("3.14"); - doublearr.addString("1.414"); - Cursor enumarr = root.setArray("enumarr"); - enumarr.addString("VAL1"); - enumarr.addString("VAL2"); - Cursor intarr = root.setArray("intarr"); - intarr.addString("3"); - intarr.addString("5"); - Cursor longarr = root.setArray("longarr"); - longarr.addString("55"); - longarr.addString("66"); - Cursor stringarr = root.setArray("stringarr"); - stringarr.addString("foo"); - stringarr.addString("bar"); - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - InnerCNode def = new DefParser("arraytypes", new StringReader(StringUtilities.implode(ArraytypesConfig.CONFIG_DEF_SCHEMA, "\n"))).getTree(); - new ConfigFileFormat(def).encode(baos, slime); - assertEquals( - "boolarr[0] true\n" + - "boolarr[1] false\n" + - "doublearr[0] 3.14\n" + - "doublearr[1] 1.414\n" + - "enumarr[0] VAL1\n" + - "enumarr[1] VAL2\n" + - "intarr[0] 3\n" + - "intarr[1] 5\n" + - "longarr[0] 55\n" + - "longarr[1] 66\n" + - "stringarr[0] \"foo\"\n" + - "stringarr[1] \"bar\"\n", - baos.toString()); - } - - @Test - public void require_that_map_formatting_is_correct() throws IOException { - Slime slime = new Slime(); - Cursor root = slime.setObject(); - Cursor boolval = root.setObject("boolmap"); - boolval.setString("foo", "true"); - boolval.setString("bar", "false"); - root.setObject("intmap").setString("foo", "1234"); - root.setObject("longmap").setString("foo", "12345"); - root.setObject("doublemap").setString("foo", "3.14"); - root.setObject("stringmap").setString("foo", "bar"); - root.setObject("innermap").setObject("bar").setString("foo", "1234"); - root.setObject("nestedmap").setObject("baz").setObject("inner").setString("foo", "1234"); - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - InnerCNode def = new DefParser("maptypes", new StringReader(StringUtilities.implode(MaptypesConfig.CONFIG_DEF_SCHEMA, "\n"))).getTree(); - new ConfigFileFormat(def).encode(baos, slime); - assertEquals( - "boolmap{\"foo\"} true\n" + - "boolmap{\"bar\"} false\n" + - "intmap{\"foo\"} 1234\n" + - "longmap{\"foo\"} 12345\n" + - "doublemap{\"foo\"} 3.14\n" + - "stringmap{\"foo\"} \"bar\"\n" + - "innermap{\"bar\"}.foo 1234\n" + - "nestedmap{\"baz\"}.inner{\"foo\"} 1234\n", - baos.toString()); - } - - @Test - public void require_that_struct_formatting_is_correct() throws IOException { - Slime slime = new Slime(); - Cursor root = slime.setObject(); - Cursor simple = root.setObject("simple"); - simple.setString("name", "myname"); - simple.setString("gender", "FEMALE"); - Cursor array = simple.setArray("emails"); - array.addString("foo@bar.com"); - array.addString("bar@baz.net"); - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - InnerCNode def = new DefParser("structtypes", new StringReader(StringUtilities.implode(StructtypesConfig.CONFIG_DEF_SCHEMA, "\n"))).getTree(); - new ConfigFileFormat(def).encode(baos, slime); - assertEquals( - "simple.name \"myname\"\n" + - "simple.gender FEMALE\n" + - "simple.emails[0] \"foo@bar.com\"\n" + - "simple.emails[1] \"bar@baz.net\"\n", - baos.toString()); - } - - @Test - public void require_that_complex_struct_formatting_is_correct() throws IOException { - Slime slime = new Slime(); - Cursor root = slime.setObject(); - - Cursor nested = root.setObject("nested"); - Cursor nested_inner = nested.setObject("inner"); - nested_inner.setString("name", "baz"); - nested_inner.setString("gender", "FEMALE"); - Cursor nested_inner_arr = nested_inner.setArray("emails"); - nested_inner_arr.addString("foo"); - nested_inner_arr.addString("bar"); - - Cursor nestedarr = root.setArray("nestedarr"); - Cursor nestedarr1 = nestedarr.addObject(); - Cursor inner1 = nestedarr1.setObject("inner"); - inner1.setString("name", "foo"); - inner1.setString("gender", "FEMALE"); - Cursor inner1arr = inner1.setArray("emails"); - inner1arr.addString("foo@bar"); - inner1arr.addString("bar@foo"); - - Cursor complexarr = root.setArray("complexarr"); - Cursor complexarr1 = complexarr.addObject(); - Cursor innerarr1 = complexarr1.setArray("innerarr"); - Cursor innerarr11 = innerarr1.addObject(); - innerarr11.setString("name", "bar"); - innerarr11.setString("gender", "MALE"); - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - InnerCNode def = new DefParser("structtypes", new StringReader(StringUtilities.implode(StructtypesConfig.CONFIG_DEF_SCHEMA, "\n"))).getTree(); - new ConfigFileFormat(def).encode(baos, slime); - assertEquals("nested.inner.name \"baz\"\n" + - "nested.inner.gender FEMALE\n" + - "nested.inner.emails[0] \"foo\"\n" + - "nested.inner.emails[1] \"bar\"\n" + - "nestedarr[0].inner.name \"foo\"\n" + - "nestedarr[0].inner.gender FEMALE\n" + - "nestedarr[0].inner.emails[0] \"foo@bar\"\n" + - "nestedarr[0].inner.emails[1] \"bar@foo\"\n" + - "complexarr[0].innerarr[0].name \"bar\"\n" + - "complexarr[0].innerarr[0].gender MALE\n", - baos.toString()); - } - - @Test - public void require_that_strings_are_properly_escaped() throws IOException { - Slime slime = new Slime(); - Cursor root = slime.setObject(); - root.setString("stringval", "some\"quotes\\\"instring"); - InnerCNode def = new DefParser("simpletypes", new StringReader(StringUtilities.implode(SimpletypesConfig.CONFIG_DEF_SCHEMA, "\n"))).getTree(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - new ConfigFileFormat(def).encode(baos, slime); - assertEquals("stringval \"some\\\"quotes\\\\\\\"instring\"\n", baos.toString()); - } - - @Test - @Ignore - public void require_that_utf8_works() throws IOException { - Slime slime = new Slime(); - Cursor root = slime.setObject(); - final String input = "Hei \u00E6\u00F8\u00E5 \n \uBC14\uB451 \u00C6\u00D8\u00C5 hallo"; - root.setString("stringval", input); - System.out.println(bytesToHexString(Utf8.toBytes(input))); - InnerCNode def = new DefParser("simpletypes", new StringReader(StringUtilities.implode(SimpletypesConfig.CONFIG_DEF_SCHEMA, "\n"))).getTree(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - new ConfigFileFormat(def).encode(baos, slime); - System.out.println(bytesToHexString(baos.toByteArray())); - assertEquals(Utf8.toString(baos.toByteArray()), "stringval \"" + input + "\"\n"); - } - - private static String bytesToHexString(byte[] bytes){ - StringBuilder sb = new StringBuilder(); - for(byte b : bytes){ - sb.append(String.format("%02x", b&0xff)); - } - return sb.toString(); - } -} -- cgit v1.2.3