stdlib_test.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  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 stdlib
  11. import (
  12. "fmt"
  13. "math"
  14. "plugin"
  15. "reflect"
  16. "strings"
  17. "testing"
  18. )
  19. func TestGetPkgDocString(t *testing.T) {
  20. AddStdlibPkg("foo", "foo doc")
  21. mathFuncMap["Println"] = &ECALFunctionAdapter{reflect.ValueOf(fmt.Println), "foo"}
  22. f, _ := GetStdlibFunc("math.Println")
  23. if s, _ := f.DocString(); s != "foo" {
  24. t.Error("Unexpected result:", s)
  25. return
  26. }
  27. doc, _ := GetPkgDocString("math")
  28. if doc == "" {
  29. t.Error("Unexpected result:", doc)
  30. return
  31. }
  32. doc, _ = GetPkgDocString("foo")
  33. if doc != "foo doc" {
  34. t.Error("Unexpected result:", doc)
  35. return
  36. }
  37. if err := AddStdlibPkg("foo", "foo doc"); err == nil || err.Error() != "Package foo already exists" {
  38. t.Error("Unexpected error:", err)
  39. return
  40. }
  41. }
  42. func TestSymbols(t *testing.T) {
  43. AddStdlibPkg("foo", "foo doc")
  44. AddStdlibFunc("foo", "bar", nil)
  45. p, c, f := GetStdlibSymbols()
  46. if len(p) == 0 || len(c) == 0 || len(f) == 0 {
  47. t.Error("Should have some entries in symbol lists:", p, c, f)
  48. return
  49. }
  50. }
  51. func TestSplitModuleAndName(t *testing.T) {
  52. if m, n := splitModuleAndName("fmt.Println"); m != "fmt" || n != "Println" {
  53. t.Error("Unexpected result:", m, n)
  54. return
  55. }
  56. if m, n := splitModuleAndName(""); m != "" || n != "" {
  57. t.Error("Unexpected result:", m, n)
  58. return
  59. }
  60. if m, n := splitModuleAndName("a"); m != "a" || n != "" {
  61. t.Error("Unexpected result:", m, n)
  62. return
  63. }
  64. if m, n := splitModuleAndName("my.FuncCall"); m != "my" || n != "FuncCall" {
  65. t.Error("Unexpected result:", m, n)
  66. return
  67. }
  68. }
  69. func TestGetStdLibItems(t *testing.T) {
  70. dummyFunc := &ECALFunctionAdapter{}
  71. AddStdlibFunc("foo", "bar", dummyFunc)
  72. mathFuncMap["Println"] = &ECALFunctionAdapter{reflect.ValueOf(fmt.Println), "foo"}
  73. if f, _ := GetStdlibFunc("math.Println"); f != mathFuncMap["Println"] {
  74. t.Error("Unexpected resutl: functions should lookup correctly")
  75. return
  76. }
  77. if f, _ := GetStdlibFunc("foo.bar"); f != dummyFunc {
  78. t.Error("Unexpected resutl: functions should lookup correctly")
  79. return
  80. }
  81. if c, ok := GetStdlibFunc("foo"); c != nil || ok {
  82. t.Error("Unexpected resutl: func should lookup correctly")
  83. return
  84. }
  85. if c, _ := GetStdlibConst("math.Pi"); c != math.Pi {
  86. t.Error("Unexpected resutl: constants should lookup correctly")
  87. return
  88. }
  89. if c, ok := GetStdlibConst("foo"); c != nil || ok {
  90. t.Error("Unexpected resutl: constants should lookup correctly")
  91. return
  92. }
  93. }
  94. func TestAddStdLibFunc(t *testing.T) {
  95. dummyFunc := &ECALFunctionAdapter{}
  96. AddStdlibFunc("foo", "bar", dummyFunc)
  97. if f, _ := GetStdlibFunc("foo.bar"); f != dummyFunc {
  98. t.Error("Unexpected resutl: functions should lookup correctly")
  99. return
  100. }
  101. if err := AddStdlibFunc("foo2", "bar", dummyFunc); err == nil || err.Error() != "Package foo2 does not exist" {
  102. t.Error("Unexpected error:", err)
  103. return
  104. }
  105. }
  106. func TestAddPluginStdLibFunc(t *testing.T) {
  107. var err error
  108. // Uncomment the commented parts in this test to run against an
  109. // actual compiled plugin in the examples/plugin directory
  110. /*
  111. err = AddStdlibPluginFunc("foo", "bar", filepath.Join("..", "examples", "plugin", "myfunc.so"), "ECALmyfunc")
  112. if err != nil {
  113. t.Error("Unexpected result:", err)
  114. return
  115. }
  116. */
  117. pluginTestLookup = &testLookup{&testECALPluginFunction{}, nil}
  118. err = AddStdlibPluginFunc("foo", "bar", "", "ECALmyfunc")
  119. pluginTestLookup = nil
  120. if err != nil {
  121. t.Error("Unexpected result:", err)
  122. return
  123. }
  124. pluginTestLookup = &testLookup{&testECALPluginFunction{}, nil}
  125. errs := LoadStdlibPlugins([]interface{}{
  126. map[string]interface{}{
  127. "package": "foo",
  128. "name": "bar",
  129. "path": "",
  130. "symbol": "ECALmyfunc",
  131. },
  132. map[string]interface{}{
  133. "package": "foo",
  134. "name": "bar",
  135. "path": "",
  136. "symbol": "showerror",
  137. },
  138. })
  139. pluginTestLookup = nil
  140. if fmt.Sprint(errs) != "[Test lookup error]" {
  141. t.Error("Unexpected result:", errs)
  142. return
  143. }
  144. pfunc, ok := GetStdlibFunc("foo.bar")
  145. if !ok {
  146. t.Error("Unexpected result:", pfunc, ok)
  147. return
  148. }
  149. res, err := pfunc.Run("", nil, nil, 0, []interface{}{"John"})
  150. if err != nil || res != "Hello World for John" {
  151. t.Error("Unexpected result:", res, err)
  152. return
  153. }
  154. // Test errors
  155. /*
  156. err = AddStdlibPluginFunc("foo", "bar", filepath.Join("..", "examples", "plugin", "myfunc.so"), "Greeting")
  157. if err == nil || err.Error() != "Symbol Greeting is not a stdlib function" {
  158. t.Error("Unexpected result:", err)
  159. return
  160. }
  161. err = AddStdlibPluginFunc("foo", "bar", filepath.Join("..", "examples", "plugin", "myfunc.so"), "foo")
  162. if err == nil || !strings.Contains(err.Error(), "symbol foo not found") {
  163. t.Error("Unexpected result:", err)
  164. return
  165. }
  166. */
  167. pluginTestLookup = &testLookup{"foo", nil}
  168. err = AddStdlibPluginFunc("foo", "bar", "", "Greeting")
  169. if err == nil || err.Error() != "Symbol Greeting is not a stdlib function" {
  170. t.Error("Unexpected result:", err)
  171. return
  172. }
  173. pluginTestLookup = &testLookup{nil, fmt.Errorf("symbol foo not found")}
  174. err = AddStdlibPluginFunc("foo", "bar", "", "foo")
  175. if err == nil || !strings.Contains(err.Error(), "symbol foo not found") {
  176. t.Error("Unexpected result:", err)
  177. return
  178. }
  179. }
  180. type testLookup struct {
  181. ret interface{}
  182. err error
  183. }
  184. func (tl *testLookup) Lookup(symName string) (plugin.Symbol, error) {
  185. if symName == "showerror" {
  186. return nil, fmt.Errorf("Test lookup error")
  187. }
  188. return tl.ret, tl.err
  189. }
  190. type testECALPluginFunction struct {
  191. }
  192. func (tf *testECALPluginFunction) Run(args []interface{}) (interface{}, error) {
  193. if len(args) == 0 {
  194. return "", fmt.Errorf("Need a name to greet as argument")
  195. }
  196. return fmt.Sprintf("Hello World for %v", args[0]), nil
  197. }
  198. func (tf *testECALPluginFunction) DocString() string {
  199. return "Myfunc is an example function"
  200. }