Skip to content

Commit

Permalink
Resolved issue #3 and #4 with the suggestion of #4.
Browse files Browse the repository at this point in the history
Added a small test which shows that the anchors are.
  • Loading branch information
Christoph Keiner committed Feb 18, 2019
1 parent 3c5249a commit 75f2f78
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 13 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>com.xceptance</groupId>
<artifactId>xlt-nocoding</artifactId>
<version>2.0.1</version>
<version>2.0.2</version>

<name>xlt-nocoding</name>
<description>A library based on XLT to run Web test cases that are written in either YAML or CSV format.</description>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
package com.xceptance.xlt.nocoding.parser.yaml;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import org.yaml.snakeyaml.Yaml;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SequenceWriter;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.xceptance.xlt.api.util.XltLogger;
Expand Down Expand Up @@ -44,21 +49,20 @@ public class YamlParser implements Parser
public List<Command> parse(final String pathToFile) throws IOException
{
final List<Command> scriptItems = new ArrayList<>();
// Build the factory
final YAMLFactory factory = new YAMLFactory();

// Generate a Reader based on the file
final Reader reader = createReader(pathToFile);
// Resolve Anchors
final ByteArrayOutputStream anchorlessYaml = resolveAnchors(pathToFile);
// Place the content inside an ByteArryInputSteam
final ByteArrayInputStream anchorlessYamlInputSteam = new ByteArrayInputStream(anchorlessYaml.toByteArray());
// Create the parser
final JsonParser parser = factory.createParser(reader);
final JsonParser parser = new YAMLFactory().createParser(anchorlessYamlInputSteam);
// Allow comments in the parser, so we have the correct line numbers
parser.enable(com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_COMMENTS);
parser.enable(Feature.ALLOW_YAML_COMMENTS);

// Create an ObjectMapper
final ObjectMapper mapper = new ObjectMapper();
final ObjectMapper mapperYaml = new ObjectMapper();
// Map the parsed content to JsonNodes, which are easier to use
final JsonNode root = mapper.readTree(parser);
final JsonNode root = mapperYaml.readTree(parser);

// Check that the root, which consists of the list items, is an ArrayNode
if (root != null)
Expand Down Expand Up @@ -89,7 +93,7 @@ public List<Command> parse(final String pathToFile) throws IOException
// Check if we have a permitted list item
if (Constants.isPermittedListItem(currentName))
{
XltLogger.runTimeLogger.info(numberObject + ".th ScriptItem: " + currentName);
XltLogger.runTimeLogger.info(numberObject + ". ScriptItem: " + currentName);

// Try and catch, so we can use a JsonParseException, which prints the line/column number
try
Expand Down Expand Up @@ -131,6 +135,31 @@ public List<Command> parse(final String pathToFile) throws IOException
return scriptItems;
}

/**
* Resolves anchors and aliases in the Yaml-file and returns an ByteArrayOutputStream.<br>
* Since Jackson cannot resolve anchors and aliases, snakeyml is used to parse it to objects, which are then
* transformed via Jackson's {@link SequenceWriter}.
*
* @param pathToFile
* The String that describes the path to the file
* @return A ByteArrayOutputStream with the anchors resolved as their own object.
* @throws IOException
* If a {@link Reader} or {@link SequenceWriter} cannot be created.
*/
protected ByteArrayOutputStream resolveAnchors(final String pathToFile) throws IOException
{
// Parse the Yaml with snakeyml
final Yaml yaml = new Yaml();
final Object loadedYaml = yaml.load(createReader(pathToFile));

// Place the parsed Yaml with Jacksons SequenceWriter in an ByteArrayOutputSteam
final ByteArrayOutputStream anchorlessYaml = new ByteArrayOutputStream();
final SequenceWriter sw = new ObjectMapper().writerWithDefaultPrettyPrinter().writeValues(anchorlessYaml);
sw.write(loadedYaml);
// Place the content inside an ByteArryInputSteam
return anchorlessYaml;
}

@Override
public List<String> getExtensions()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.xceptance.xlt.nocoding.parser.yaml;

import java.io.FileNotFoundException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.junit.Assert;
import org.junit.Test;
Expand All @@ -20,6 +23,8 @@ public class YamlParserTest extends AbstractParserTest
{
protected final String fileEmptyFile = path + "emptyFile.yml";

protected final String fileReferenceParsing = path + "referenceParsing.yml";

protected final String fileNotExistingFile = path + "notExistingFile.yml";

protected final String fileSyntaxErrorRoot = path + "syntaxErrorRoot.yml";
Expand All @@ -39,6 +44,31 @@ public void testEmptyFileParsing() throws Exception
Assert.assertTrue(scriptItems.isEmpty());
}

/**
* Verifies yaml references can be parsed
*
* @throws Exception
*/
@Test
public void testReferenceFileParsing() throws Exception
{
final String patternString = "\"Action\"\\s:\\s(.*(?:[\\r\\n\\t].*)+)\\}(?:.*(?:[\\r\\n\\t].*)+)\"Action\"\\s:\\s(.*(?:[\\r\\n\\t].*)+)\\}";
// final String patternString =
// "\"Action\"\\s:\\s(.*(?:[\\r\\n\\t].*)+)\\}\\,\\s\\{\\n\\s\\s\"Action\"\\s:\\s(.*(?:[\\r\\n\\t].*)+)\\}";
final YamlParser parser = new YamlParser();
final String anchorlessYaml = parser.resolveAnchors(fileReferenceParsing).toString(StandardCharsets.UTF_8.name());
final Pattern pattern = Pattern.compile(patternString);
// final Pattern pattern =
// Pattern.compile("\"Action\"\\s:\\s(.*(?:[\\r\\n\\t].*)+)\"Action\"\\s:\\s(.*(?:[\\r\\n\\t].*)+)}");
final Matcher matcher = pattern.matcher(anchorlessYaml);
while (matcher.find())
{
final String firstGroup = matcher.group(1);
final String secondGroup = matcher.group(2);
Assert.assertTrue(firstGroup.contentEquals(secondGroup));
}
}

/**
* Verifies an error is thrown if the file is not found
*
Expand All @@ -49,7 +79,8 @@ public void testNotExistingFileParsing() throws Exception
{
final Parser parser = new YamlParser();
final List<Command> scriptItems = parser.parse(fileNotExistingFile);
Assert.assertTrue(scriptItems.isEmpty());
Assert.assertFalse(scriptItems.isEmpty());
Assert.assertEquals(2, scriptItems.size());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.io.IOException;

import org.junit.Test;
import org.yaml.snakeyaml.scanner.ScannerException;

import com.fasterxml.jackson.core.JsonParseException;
import com.xceptance.xlt.nocoding.parser.AbstractParserTest;
Expand Down Expand Up @@ -83,11 +84,12 @@ public void testSyntaxErrorSubrequestsObjectNotArrayParsing() throws IOException
}

/**
* Verifies an error happens when "Static" beneath "Subrequests" has objects beneath it and not arrays
* Verifies an error happens when "Static" beneath "Subrequests" has objects beneath it and not arrays.<br>
* Since Snakeyml parses once before Jackson and this isn't valid syntax, a Snakeyml exception is excepted.
*
* @throws IOException
*/
@Test(expected = JsonParseException.class)
@Test(expected = ScannerException.class)
public void testSyntaxErrorSubrequestsStaticItemObjectNotArrayParsing() throws IOException
{
final Parser parser = new YamlParser();
Expand Down
9 changes: 9 additions & 0 deletions src/test/resources/test-scripts/referenceParsing.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
- Action : &id1
Name : Reference Action
Request :
Url : https://localhost:8443/
Method : GET
Response :
Httpcode : 200

- Action: *id1

0 comments on commit 75f2f78

Please sign in to comment.