mirror of
https://github.com/opennetworkinglab/onos.git
synced 2025-10-17 02:11:38 +02:00
[ONOS-3878, 3876, 3879] Yang Parser Manager with Stack and Error Validation
Change-Id: I10e68bd676eca4d576de1234fbb67026c7b49939
This commit is contained in:
parent
fdbc0fc36c
commit
8889763e9a
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright 2016 Open Networking Laboratory
|
||||
*
|
||||
* 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 org.onosproject.yangutils.parser.impl;
|
||||
|
||||
import org.antlr.v4.runtime.ANTLRFileStream;
|
||||
import org.antlr.v4.runtime.ANTLRInputStream;
|
||||
import org.antlr.v4.runtime.CommonTokenStream;
|
||||
import org.antlr.v4.runtime.tree.ParseTree;
|
||||
import org.antlr.v4.runtime.tree.ParseTreeWalker;
|
||||
import org.onosproject.yangutils.datamodel.YangNode;
|
||||
import org.onosproject.yangutils.parser.YangUtilsParser;
|
||||
import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangLexer;
|
||||
import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser;
|
||||
import org.onosproject.yangutils.parser.exceptions.ParserException;
|
||||
import org.onosproject.yangutils.parser.impl.parserutils.ParseTreeErrorListener;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Manages file parsing, parse tree creation and data model tree creation
|
||||
* corresponding to an input YANG file.
|
||||
*/
|
||||
public class YangUtilsParserManager implements YangUtilsParser {
|
||||
|
||||
@Override
|
||||
public YangNode getDataModel(String yangFile) throws IOException, ParserException {
|
||||
|
||||
/**
|
||||
* Create a char stream that reads from YANG file. Throws an exception
|
||||
* in case input YANG file is either null or non existent.
|
||||
*/
|
||||
ANTLRInputStream input = null;
|
||||
try {
|
||||
input = new ANTLRFileStream(yangFile);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
|
||||
// Create a lexer that feeds off of input char stream.
|
||||
GeneratedYangLexer lexer = new GeneratedYangLexer(input);
|
||||
|
||||
// Create a buffer of tokens pulled from the lexer.
|
||||
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||
|
||||
// Create a parser that feeds off the tokens buffer.
|
||||
GeneratedYangParser parser = new GeneratedYangParser(tokens);
|
||||
|
||||
// Remove console error listener.
|
||||
parser.removeErrorListeners();
|
||||
|
||||
// Create instance of customized error listener.
|
||||
ParseTreeErrorListener parseTreeErrorListener = new ParseTreeErrorListener();
|
||||
|
||||
// Add customized error listener to catch errors during parsing.
|
||||
parser.addErrorListener(parseTreeErrorListener);
|
||||
|
||||
// Begin parsing YANG file and generate parse tree.
|
||||
ParseTree tree = parser.yangfile();
|
||||
|
||||
/**
|
||||
* Throws an parser Exception if exception flag is set i.e. exception has
|
||||
* occurred during parsing.
|
||||
*/
|
||||
if (parseTreeErrorListener.isExceptionFlag()) {
|
||||
// Get the exception occurred during parsing.
|
||||
ParserException parserException = parseTreeErrorListener.getParserException();
|
||||
parserException.setFileName(yangFile);
|
||||
throw parserException;
|
||||
}
|
||||
|
||||
// Create a walker to walk the parse tree.
|
||||
ParseTreeWalker walker = new ParseTreeWalker();
|
||||
|
||||
// Create a listener implementation class object.
|
||||
TreeWalkListener treeWalker = new TreeWalkListener();
|
||||
|
||||
/**
|
||||
* Walk parse tree, provide call backs to methods in listener and
|
||||
* build data model tree.
|
||||
*/
|
||||
walker.walk(treeWalker, tree);
|
||||
|
||||
// Throws an parser exception which has occurred during listener walk.
|
||||
if (treeWalker.getErrorInformation().isErrorFlag()) {
|
||||
// Create object of listener exception
|
||||
ParserException listenerException = new ParserException();
|
||||
listenerException.setMsg(treeWalker.getErrorInformation().getErrorMsg());
|
||||
listenerException.setFileName(yangFile);
|
||||
throw listenerException;
|
||||
}
|
||||
|
||||
// Returns the Root Node of the constructed data model tree.
|
||||
return treeWalker.getRootNode();
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2016 Open Networking Laboratory
|
||||
*
|
||||
* 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 org.onosproject.yangutils.parser.impl.parserutils;
|
||||
|
||||
import org.onosproject.yangutils.parser.impl.TreeWalkListener;
|
||||
|
||||
/**
|
||||
* Its a utility to carry out listener validation.
|
||||
*/
|
||||
public final class ListenerValidation {
|
||||
|
||||
/**
|
||||
* Creates a new belongto listener.
|
||||
*/
|
||||
private ListenerValidation() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if error is set or parsed data stack is empty.
|
||||
*
|
||||
* @param listener Listener's object.
|
||||
* @param errNode parsable node for which validation needs to be done.
|
||||
* @return validation result.
|
||||
*/
|
||||
public static boolean preValidation(TreeWalkListener listener, String errNode) {
|
||||
|
||||
// Check whether error found while walking YANG file, if yes return true.
|
||||
if (listener.getErrorInformation().isErrorFlag()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If stack is empty it indicates error condition
|
||||
if (listener.getParsedDataStack().empty()) {
|
||||
listener.getErrorInformation().setErrorFlag(true);
|
||||
listener.getErrorInformation().setErrorMsg("Parsable stack empty at" + errNode + "entry");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2016 Open Networking Laboratory
|
||||
*
|
||||
* 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 org.onosproject.yangutils.parser.impl.parserutils;
|
||||
|
||||
import org.antlr.v4.runtime.BaseErrorListener;
|
||||
import org.antlr.v4.runtime.RecognitionException;
|
||||
import org.antlr.v4.runtime.Recognizer;
|
||||
import org.onosproject.yangutils.parser.exceptions.ParserException;
|
||||
|
||||
/**
|
||||
* By default, ANTLR sends all errors to standard error, this is changed by
|
||||
* providing this new implementation of interface ANTLRErrorListener. The
|
||||
* interface has a syntaxError() method that applies to both lexer and
|
||||
* parser.
|
||||
*/
|
||||
public class ParseTreeErrorListener extends BaseErrorListener {
|
||||
|
||||
// Exception of type parser exceptions are catched during parsing.
|
||||
private ParserException parserException = new ParserException();
|
||||
|
||||
// Flag to indicate presence of exception.
|
||||
private boolean exceptionFlag = false;
|
||||
|
||||
/**
|
||||
* Returns the status of exception flag.
|
||||
*
|
||||
* @return flag which contains the status of exception.
|
||||
*/
|
||||
public boolean isExceptionFlag() {
|
||||
return exceptionFlag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parser exception object populated with line, character
|
||||
* position and message.
|
||||
*
|
||||
* @return object of parser exception.
|
||||
*/
|
||||
public ParserException getParserException() {
|
||||
return parserException;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine,
|
||||
String msg, RecognitionException e) {
|
||||
parserException.setLine(line);
|
||||
parserException.setCharPosition(charPositionInLine);
|
||||
parserException.setMsg(msg);
|
||||
exceptionFlag = true;
|
||||
}
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright 2016 Open Networking Laboratory
|
||||
*
|
||||
* 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 org.onosproject.yangutils.parser.impl;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.onosproject.yangutils.datamodel.YangNode;
|
||||
import org.onosproject.yangutils.parser.exceptions.ParserException;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Test case for testing YANG utils parser manager.
|
||||
*/
|
||||
public class YangUtilsParserManagerTest {
|
||||
|
||||
YangUtilsParserManager manager = new YangUtilsParserManager();
|
||||
File file;
|
||||
BufferedWriter out;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
file = new File("demo.yang");
|
||||
out = new BufferedWriter(new FileWriter(file));
|
||||
}
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
file.delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* This test case checks whether the null pointer exception is generated
|
||||
* when the input YANG file is null.
|
||||
*/
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void getDataModelNullFileTest() throws IOException, ParserException {
|
||||
YangUtilsParserManager manager = new YangUtilsParserManager();
|
||||
YangNode node = manager.getDataModel(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* This test case checks whether the io exception is generated
|
||||
* when the input YANG file is non existent.
|
||||
*/
|
||||
@Test(expected = IOException.class)
|
||||
public void getDataModelNonExistentFileTest() throws IOException, ParserException {
|
||||
|
||||
YangUtilsParserManager manager = new YangUtilsParserManager();
|
||||
YangNode node = manager.getDataModel("nonexistent.yang");
|
||||
}
|
||||
|
||||
/**
|
||||
* This test case checks if the input YANG file is correct no exception
|
||||
* should be generated.
|
||||
*/
|
||||
@Test
|
||||
public void getDataModelCorrectFileTest() throws IOException, ParserException {
|
||||
|
||||
out.write("module ONOS {\n");
|
||||
out.write("yang-version 1;\n");
|
||||
out.write("namespace urn:ietf:params:xml:ns:yang:ietf-ospf;\n");
|
||||
out.write("prefix On;\n");
|
||||
out.write("}\n");
|
||||
out.close();
|
||||
|
||||
YangNode node = manager.getDataModel("demo.yang");
|
||||
}
|
||||
|
||||
/**
|
||||
* This test case checks if the input YANG file with wrong YANG constructs
|
||||
* than parser exception should be generated.
|
||||
*/
|
||||
@Test(expected = ParserException.class)
|
||||
public void getDataModelIncorrectFileTest() throws IOException, ParserException {
|
||||
|
||||
out.write("module ONOS {\n");
|
||||
out.write("yang-version 1\n");
|
||||
out.write("namespace urn:ietf:params:xml:ns:yang:ietf-ospf;\n");
|
||||
out.write("prefix On;\n");
|
||||
out.write("}\n");
|
||||
out.close();
|
||||
|
||||
YangNode node = manager.getDataModel("demo.yang");
|
||||
}
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright 2016 Open Networking Laboratory
|
||||
*
|
||||
* 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 org.onosproject.yangutils.parser.parseutils;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.onosproject.yangutils.datamodel.YangRevision;
|
||||
import org.onosproject.yangutils.parser.impl.TreeWalkListener;
|
||||
import org.onosproject.yangutils.parser.impl.parserutils.ListenerError;
|
||||
import org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation;
|
||||
|
||||
import static org.hamcrest.core.Is.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* Test case for testing listener validation util.
|
||||
*/
|
||||
public class ListenerValidationTest {
|
||||
|
||||
/**
|
||||
* This test case checks in case error pre-exists, listener validate
|
||||
* function returns true.
|
||||
*/
|
||||
@Test
|
||||
public void listenerValidationErrorExists() {
|
||||
|
||||
// Create an test error.
|
||||
ListenerError testError = new ListenerError();
|
||||
testError.setErrorFlag(true);
|
||||
testError.setErrorMsg("Test Error");
|
||||
|
||||
// Create test walker and assign test error to it.
|
||||
TreeWalkListener testWalker = new TreeWalkListener();
|
||||
testWalker.setErrorInformation(testError);
|
||||
|
||||
// Create a temporary node of parsable.
|
||||
YangRevision tmpNode = new YangRevision();
|
||||
testWalker.getParsedDataStack().push(tmpNode);
|
||||
|
||||
boolean errorFlag = ListenerValidation.preValidation(testWalker, "ErrorTest");
|
||||
|
||||
/**
|
||||
* Check for the values set in syntax error function. If not set properly
|
||||
* report an assert.
|
||||
*/
|
||||
assertThat(errorFlag, is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* This test case checks in case parsable stack is empty, listener validate
|
||||
* function returns true.
|
||||
*/
|
||||
@Test
|
||||
public void listenerValidationEmptyStack() {
|
||||
|
||||
// Create test walker and assign test error to it.
|
||||
TreeWalkListener testWalker = new TreeWalkListener();
|
||||
|
||||
boolean errorFlag = ListenerValidation.preValidation(testWalker, "ErrorTest");
|
||||
|
||||
/**
|
||||
* Check for the values set in syntax error function. If not set properly
|
||||
* report an assert.
|
||||
*/
|
||||
assertThat(errorFlag, is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* This test case checks in case of error doesn't pre-exists and stack is,
|
||||
* non empty, listener validate function returns false.
|
||||
*/
|
||||
@Test
|
||||
public void listenerValidationNoErrorNotExists() {
|
||||
|
||||
// Create test walker and assign test error to it.
|
||||
TreeWalkListener testWalker = new TreeWalkListener();
|
||||
|
||||
// Create a temporary node of parsable.
|
||||
YangRevision tmpNode = new YangRevision();
|
||||
testWalker.getParsedDataStack().push(tmpNode);
|
||||
|
||||
boolean errorFlag = ListenerValidation.preValidation(testWalker, "ErrorTest");
|
||||
|
||||
/**
|
||||
* Check for the values set in syntax error function. If not set properly
|
||||
* report an assert.
|
||||
*/
|
||||
assertThat(errorFlag, is(false));
|
||||
}
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright 2016 Open Networking Laboratory
|
||||
*
|
||||
* 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 org.onosproject.yangutils.parser.impl.parseutils;
|
||||
|
||||
import org.antlr.v4.runtime.ANTLRFileStream;
|
||||
import org.antlr.v4.runtime.ANTLRInputStream;
|
||||
import org.antlr.v4.runtime.CommonTokenStream;
|
||||
import org.antlr.v4.runtime.tree.ParseTree;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangLexer;
|
||||
import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser;
|
||||
import org.onosproject.yangutils.parser.exceptions.ParserException;
|
||||
import org.onosproject.yangutils.parser.impl.YangUtilsParserManager;
|
||||
import org.onosproject.yangutils.parser.impl.parserutils.ParseTreeErrorListener;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.hamcrest.core.Is.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* Test case for testing parse tree error listener.
|
||||
*/
|
||||
public class ParseTreeErrorListenerTest {
|
||||
|
||||
YangUtilsParserManager manager = new YangUtilsParserManager();
|
||||
File file;
|
||||
BufferedWriter out;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
file = new File("demo.yang");
|
||||
out = new BufferedWriter(new FileWriter(file));
|
||||
}
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
file.delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* This test case checks whether the error received from parser is correctly
|
||||
* handled.
|
||||
*/
|
||||
@Test
|
||||
public void syntaxErrorValidationTest() throws IOException {
|
||||
|
||||
out.write("module ONOS {\n");
|
||||
out.write("yang-version 1\n");
|
||||
out.write("namespace urn:ietf:params:xml:ns:yang:ietf-ospf;\n");
|
||||
out.write("prefix On;\n");
|
||||
out.write("}\n");
|
||||
out.close();
|
||||
|
||||
ANTLRInputStream input = new ANTLRFileStream("demo.yang");
|
||||
|
||||
// Create a lexer that feeds off of input char stream.
|
||||
GeneratedYangLexer lexer = new GeneratedYangLexer(input);
|
||||
// Create a buffer of tokens pulled from the lexer.
|
||||
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||
// Create a parser that feeds off the tokens buffer.
|
||||
GeneratedYangParser parser = new GeneratedYangParser(tokens);
|
||||
// Remove console error listener.
|
||||
parser.removeErrorListeners();
|
||||
// Create instance of customized error listener.
|
||||
ParseTreeErrorListener parseTreeErrorListener = new ParseTreeErrorListener();
|
||||
// Add customized error listener to catch errors during parsing.
|
||||
parser.addErrorListener(parseTreeErrorListener);
|
||||
// Begin parsing YANG file and generate parse tree.
|
||||
ParseTree tree = parser.yangfile();
|
||||
// Get the exception occurred during parsing.
|
||||
ParserException parserException = parseTreeErrorListener.getParserException();
|
||||
|
||||
/**
|
||||
* Check for the values set in syntax error function. If not set properly
|
||||
* report an assert.
|
||||
*/
|
||||
assertThat(parseTreeErrorListener.isExceptionFlag(), is(true));
|
||||
assertThat(parserException.getLineNumber(), is(3));
|
||||
assertThat(parserException.getCharPositionInLine(), is(0));
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user