123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- /*
- * ECAL
- *
- * Copyright 2020 Matthias Ladkau. All rights reserved.
- *
- * This Source Code Form is subject to the terms of the MIT
- * License, If a copy of the MIT License was not distributed with this
- * file, You can obtain one at https://opensource.org/licenses/MIT.
- */
- package parser
- import (
- "encoding/json"
- "flag"
- "fmt"
- "os"
- "testing"
- )
- // Main function for all tests in this package
- func TestMain(m *testing.M) {
- flag.Parse()
- res := m.Run()
- // Check if all nodes have been tested
- for _, n := range astNodeMap {
- if _, ok := usedNodes[n.Name]; !ok {
- fmt.Println("Not tested node: ", n.Name)
- }
- }
- // Check if all nodes have been pretty printed
- for k := range prettyPrinterMap {
- if _, ok := usedPrettyPrinterNodes[k]; !ok {
- fmt.Println("Not tested pretty printer: ", k)
- }
- }
- os.Exit(res)
- }
- // Used nodes map which is filled during unit testing. Prefilled with tokens which
- // will not be generated by the parser
- //
- var usedNodes = map[string]bool{
- NodeEOF: true, // Only used as end term
- "": true, // No node e.g. semicolon - These nodes should never be part of an AST
- }
- func UnitTestParse(name string, input string) (*ASTNode, error) {
- return UnitTestParseWithPPResult(name, input, "")
- }
- func UnitTestParseWithPPResult(name string, input string, expectedPPRes string) (*ASTNode, error) {
- n, err := ParseWithRuntime(name, input, &DummyRuntimeProvider{})
- // Test AST serialization
- if err == nil {
- var unmarshaledJSONObject map[string]interface{}
- astString, err := json.Marshal(n.ToJSONObject())
- if err != nil {
- return nil, fmt.Errorf("Could not marshal AST: %v", err)
- }
- if err := json.Unmarshal(astString, &unmarshaledJSONObject); err != nil {
- return nil, fmt.Errorf("Could not unmarshal JSON object: %v", err)
- }
- unmarshaledAST, err := ASTFromJSONObject(unmarshaledJSONObject)
- if err != nil {
- return nil, fmt.Errorf("Could not create AST from unmarshaled JSON object: %v", err)
- }
- // Compare the ASTs
- if ok, msg := n.Equals(unmarshaledAST, false); !ok {
- return nil, fmt.Errorf(
- "Parsed AST is different from the unmarshaled AST."+
- "\n%v\n", msg)
- }
- }
- // Test Pretty printing
- if err == nil {
- ppres, err := PrettyPrint(n)
- if err != nil {
- return nil, fmt.Errorf("Error while pretty printing: %v (input: %v)", err, input)
- }
- if expectedPPRes == "" {
- n2, err := ParseWithRuntime(name, ppres, &DummyRuntimeProvider{})
- if err != nil {
- return nil, fmt.Errorf("Error while parsing pretty print result: %v (result: %v)", err, ppres)
- }
- // Compare the ASTs
- if ok, msg := n.Equals(n2, true); !ok {
- return nil, fmt.Errorf(
- "Parsed AST from pretty printer is different from the originally parsed AST."+
- "\nOriginal input: %v\nPretty printed: %v\nPretty AST: %v\n%v\n",
- input, ppres, n2, msg)
- }
- } else if ppres != expectedPPRes {
- return nil, fmt.Errorf("Expected pretty printer result is different:\nExpected "+
- "result: %v\nActual result: %v\n", expectedPPRes, ppres)
- }
- markASTNodesAsPrettyPrinted(n)
- }
- return n, err
- }
- // Used nodes map which is filled during unit testing. Prefilled with tokens which
- // will not be generated by the parser
- //
- var usedPrettyPrinterNodes = map[string]bool{}
- func markASTNodesAsPrettyPrinted(n *ASTNode) {
- // Make the encountered node as used
- numChildren := len(n.Children)
- if numChildren > 0 {
- usedPrettyPrinterNodes[fmt.Sprintf("%v_%v", n.Name, numChildren)] = true
- } else {
- usedPrettyPrinterNodes[n.Name] = true
- }
- for _, c := range n.Children {
- markASTNodesAsPrettyPrinted(c)
- }
- }
- func UnitTestPrettyPrinting(input, astOutput, ppOutput string) error {
- astres, err := ParseWithRuntime("mytest", input, &DummyRuntimeProvider{})
- if err != nil || (astOutput != "" && fmt.Sprint(astres) != astOutput) {
- return fmt.Errorf("Unexpected parser output:\n%v expected was:\n%v Error: %v", astres, astOutput, err)
- }
- markASTNodesAsPrettyPrinted(astres)
- ppres, err := PrettyPrint(astres)
- if err != nil || ppres != ppOutput {
- return fmt.Errorf("Unexpected result: %v (expected: %v) error: %v", ppres, ppOutput, err)
- }
- // Make sure the pretty printed result is valid and gets the same parse tree
- astres2, err := ParseWithRuntime("mytest", ppres, &DummyRuntimeProvider{})
- if err != nil || (astOutput != "" && fmt.Sprint(astres2) != astOutput) {
- return fmt.Errorf("Unexpected parser output from pretty print string:\n%v expected was:\n%v Error: %v", astres2, astOutput, err)
- }
- return nil
- }
- // Helper objects
- type DummyRuntimeProvider struct {
- }
- func (d *DummyRuntimeProvider) Runtime(n *ASTNode) Runtime {
- // Make the encountered node as used
- usedNodes[n.Name] = true
- return nil
- }
|