main_test.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /*
  2. * ECAL
  3. *
  4. * Copyright 2020 Matthias Ladkau. All rights reserved.
  5. *
  6. * This Source Code Form is subject to the terms of the MIT
  7. * License, If a copy of the MIT License was not distributed with this
  8. * file, You can obtain one at https://opensource.org/licenses/MIT.
  9. */
  10. package interpreter
  11. import (
  12. "flag"
  13. "fmt"
  14. "os"
  15. "testing"
  16. "devt.de/krotik/common/datautil"
  17. "devt.de/krotik/ecal/parser"
  18. "devt.de/krotik/ecal/scope"
  19. "devt.de/krotik/ecal/util"
  20. )
  21. // Main function for all tests in this package
  22. func TestMain(m *testing.M) {
  23. flag.Parse()
  24. // Run the tests
  25. res := m.Run()
  26. // Check if all nodes have been tested
  27. for n := range providerMap {
  28. if _, ok := usedNodes[n]; !ok {
  29. fmt.Println("Not tested node: ", n)
  30. }
  31. }
  32. os.Exit(res)
  33. }
  34. // Used nodes map which is filled during unit testing. Prefilled only with nodes
  35. // which should not be encountered in ASTs.
  36. //
  37. var usedNodes = map[string]bool{
  38. parser.NodeEOF: true,
  39. }
  40. func UnitTestEval(input string, vs parser.Scope) (interface{}, error) {
  41. return UnitTestEvalAndAST(input, vs, "")
  42. }
  43. func UnitTestEvalAndAST(input string, vs parser.Scope, expectedAST string) (interface{}, error) {
  44. return UnitTestEvalAndASTAndImport(input, vs, "", nil)
  45. }
  46. func UnitTestEvalAndASTAndImport(input string, vs parser.Scope, expectedAST string, importLocator util.ECALImportLocator) (interface{}, error) {
  47. var traverseAST func(n *parser.ASTNode)
  48. traverseAST = func(n *parser.ASTNode) {
  49. if n.Name == "" {
  50. panic(fmt.Sprintf("Node found with empty string name: %s", n))
  51. }
  52. usedNodes[n.Name] = true
  53. for _, cn := range n.Children {
  54. traverseAST(cn)
  55. }
  56. }
  57. // Parse the input
  58. ast, err := parser.ParseWithRuntime("ECALEvalTest", input,
  59. NewECALRuntimeProvider("ECALTestRuntime", importLocator))
  60. if err != nil {
  61. return nil, err
  62. }
  63. traverseAST(ast)
  64. if expectedAST != "" && ast.String() != expectedAST {
  65. return nil, fmt.Errorf("Unexpected AST result:\n%v", ast.String())
  66. }
  67. // Validate input
  68. if err := ast.Runtime.Validate(); err != nil {
  69. return nil, err
  70. }
  71. if vs == nil {
  72. vs = scope.NewScope(scope.GlobalScope)
  73. }
  74. return ast.Runtime.Eval(vs, make(map[string]interface{}))
  75. }
  76. /*
  77. addLogFunction adds a simple log function to a given Scope.
  78. */
  79. func addLogFunction(vs parser.Scope) *datautil.RingBuffer {
  80. buf := datautil.NewRingBuffer(20)
  81. vs.SetValue("log", &TestLogger{buf})
  82. return buf
  83. }
  84. /*
  85. TestLogger is a simple logger function which can be added to tess.
  86. */
  87. type TestLogger struct {
  88. buf *datautil.RingBuffer
  89. }
  90. func (tl *TestLogger) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
  91. tl.buf.Add(fmt.Sprint(args...))
  92. return nil, nil
  93. }
  94. func (tl *TestLogger) DocString() (string, error) {
  95. return "testlogger docstring", nil
  96. }
  97. func (tl *TestLogger) String() string {
  98. return "TestLogger"
  99. }
  100. func (tl *TestLogger) MarshalJSON() ([]byte, error) {
  101. return []byte(tl.String()), nil
  102. }