schema_test.go 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. // Copyright 2021-2023 EMQ Technologies Co., Ltd.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package service
  15. import (
  16. "reflect"
  17. "testing"
  18. "github.com/lf-edge/ekuiper/internal/testx"
  19. )
  20. var descriptors []descriptor
  21. func init() {
  22. schemas := []*schemaInfo{
  23. {
  24. SchemaType: PROTOBUFF,
  25. SchemaFile: "hw.proto",
  26. },
  27. }
  28. descriptors = make([]descriptor, len(schemas))
  29. for i, sch := range schemas {
  30. d, err := parse(sch.SchemaType, sch.SchemaFile)
  31. if err != nil {
  32. panic(err)
  33. }
  34. descriptors[i] = d
  35. }
  36. }
  37. func TestConvertParams(t *testing.T) {
  38. tests := []struct {
  39. method string
  40. params []interface{}
  41. iresult []interface{}
  42. jresult []byte
  43. tresult []byte
  44. err string
  45. }{
  46. { // 0
  47. method: "SayHello",
  48. params: []interface{}{
  49. "world",
  50. },
  51. iresult: []interface{}{
  52. "world",
  53. },
  54. jresult: []byte(`{"name":"world"}`),
  55. tresult: []byte(`name:"world"`),
  56. },
  57. { // 1
  58. method: "SayHello",
  59. params: []interface{}{
  60. map[string]interface{}{
  61. "name": "world",
  62. },
  63. },
  64. iresult: []interface{}{
  65. "world",
  66. },
  67. jresult: []byte(`{"name":"world"}`),
  68. tresult: []byte(`name:"world"`),
  69. },
  70. { // 2
  71. method: "SayHello",
  72. params: []interface{}{
  73. map[string]interface{}{
  74. "arbitrary": "world",
  75. },
  76. },
  77. err: "invalid type for string type field 'name': cannot convert map[string]interface {}(map[arbitrary:world]) to string",
  78. },
  79. { // 3
  80. method: "Compute",
  81. params: []interface{}{
  82. "rid", "uuid", "outlet", "path", []byte("data"), "extra",
  83. },
  84. iresult: []interface{}{
  85. "rid", "uuid", "outlet", "path", []byte("data"), "extra",
  86. },
  87. jresult: []byte(`{"rid":"rid","uuid":"uuid","outlet":"outlet","path":"path","data":"ZGF0YQ==","extra":"extra"}`),
  88. tresult: []byte(`rid:"rid" uuid:"uuid" outlet:"outlet" path:"path" data:"data" extra:"extra"`),
  89. },
  90. { // 4
  91. method: "get_feature",
  92. params: []interface{}{
  93. []byte("golang"),
  94. },
  95. iresult: []interface{}{
  96. []byte("golang"),
  97. },
  98. jresult: []byte(`"Z29sYW5n"`),
  99. tresult: []byte(`value:"golang"`),
  100. },
  101. //{ //5
  102. // method: "get_similarity",
  103. // params: []interface{}{
  104. // []float64{0.031646, -0.800592, -1.101858, -0.354359, 0.656587},
  105. // []float64{0.354359, 0.656587, -0.327047, 0.198284, -2.142494, 0.760160, 1.680131},
  106. // },
  107. // iresult: []interface{}{
  108. // []float32{0.031646, -0.800592, -1.101858, -0.354359, 0.656587},
  109. // []float32{0.354359, 0.656587, -0.327047, 0.198284, -2.142494, 0.760160, 1.680131},
  110. // },
  111. // jresult: []byte(`{"featureA":[0.031646,-0.800592,-1.101858,-0.354359,0.656587],"featureB":[0.354359,0.656587,-0.327047,0.198284,-2.142494,0.76016,1.680131]}`),
  112. //},
  113. { // 6
  114. method: "RestEncodedJson",
  115. params: []interface{}{
  116. []byte("{\"name\":\"encoded json\",\"size\":1}"),
  117. },
  118. iresult: []interface{}{
  119. "{\"name\":\"encoded json\",\"size\":1}",
  120. },
  121. jresult: []byte("{\"name\":\"encoded json\",\"size\":1}"),
  122. tresult: []byte(`value:"{\"name\":\"encoded json\",\"size\":1}"`),
  123. },
  124. { // 7
  125. method: "RestEncodedJson",
  126. params: []interface{}{
  127. []byte("{\"name\":\"encoded json\"}"),
  128. },
  129. iresult: []interface{}{
  130. "{\"name\":\"encoded json\"}",
  131. },
  132. jresult: []byte("{\"name\":\"encoded json\"}"),
  133. tresult: []byte(`value:"{\"name\":\"encoded json\"}"`),
  134. },
  135. { // 8
  136. method: "Compute",
  137. params: []interface{}{
  138. map[string]interface{}{
  139. "rid": "rid",
  140. "outlet": nil,
  141. "data": []byte("data"),
  142. },
  143. },
  144. iresult: []interface{}{
  145. "rid", nil, nil, nil, []byte("data"), nil,
  146. },
  147. jresult: []byte(`{"rid":"rid","data":"ZGF0YQ=="}`),
  148. tresult: []byte(`rid:"rid" data:"data"`),
  149. },
  150. }
  151. for i, descriptor := range descriptors {
  152. for j, tt := range tests {
  153. r, err := descriptor.(interfaceDescriptor).ConvertParams(tt.method, tt.params)
  154. if !reflect.DeepEqual(tt.err, testx.Errstring(err)) {
  155. t.Errorf("%d.%d : interface error mismatch:\n exp=%s\n got=%s\n\n", i, j, tt.err, err)
  156. } else if tt.err == "" && !reflect.DeepEqual(tt.iresult, r) {
  157. t.Errorf("%d.%d \n\ninterface result mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", i, j, tt.iresult, r)
  158. }
  159. rj, err := descriptor.(jsonDescriptor).ConvertParamsToJson(tt.method, tt.params)
  160. if !reflect.DeepEqual(tt.err, testx.Errstring(err)) {
  161. t.Errorf("%d.%d : json error mismatch:\n exp=%s\n got=%s\n\n", i, j, tt.err, err)
  162. } else if tt.err == "" && !reflect.DeepEqual(tt.jresult, rj) {
  163. t.Errorf("%d.%d \n\njson result mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", i, j, tt.jresult, rj)
  164. }
  165. tj, err := descriptor.(textDescriptor).ConvertParamsToText(tt.method, tt.params)
  166. if !reflect.DeepEqual(tt.err, testx.Errstring(err)) {
  167. t.Errorf("%d.%d : text error mismatch:\n exp=%s\n got=%s\n\n", i, j, tt.err, err)
  168. } else if tt.err == "" && !reflect.DeepEqual(tt.tresult, tj) {
  169. t.Errorf("%d.%d \n\ntext result mismatch:\n\nexp=%s\n\ngot=%s\n\n", i, j, tt.tresult, tj)
  170. }
  171. }
  172. }
  173. }
  174. func TestConvertReturns(t *testing.T) {
  175. tests := []struct {
  176. method string
  177. ireturn interface{}
  178. iresult interface{}
  179. ierr string
  180. jreturn []byte
  181. jresult interface{}
  182. jerr string
  183. }{
  184. { // 0
  185. method: "SayHello",
  186. ireturn: map[string]interface{}{"message": "world"},
  187. iresult: map[string]interface{}{"message": "world"},
  188. jreturn: []byte(`{"message":"world"}`),
  189. jresult: map[string]interface{}{"message": "world"},
  190. },
  191. { // 1
  192. method: "SayHello",
  193. ireturn: map[string]interface{}{"message": 65},
  194. ierr: "invalid type of return value for 'message': cannot convert int(65) to string",
  195. jreturn: []byte(`{"message":65}`),
  196. jerr: "invalid type of return value for 'message': cannot convert float64(65) to string",
  197. },
  198. //{
  199. // method: "SayHello",
  200. // ireturn: map[string]interface{}{
  201. // "mess":"world",
  202. // },
  203. // jreturn: []byte(`{"mess":"world"}`),
  204. //err: "invalid type for field 'message', expect string but got int)",
  205. //},
  206. { // 2
  207. method: "Compute",
  208. ireturn: map[string]interface{}{
  209. "code": int64(200),
  210. "msg": "success",
  211. },
  212. iresult: map[string]interface{}{
  213. "code": int64(200),
  214. "msg": "success",
  215. },
  216. jreturn: []byte(`{"code":200,"msg":"success"}`),
  217. jresult: map[string]interface{}{
  218. "code": int64(200),
  219. "msg": "success",
  220. },
  221. },
  222. {
  223. method: "get_feature",
  224. ireturn: map[string]interface{}{"feature": []interface{}{ // TODO check msgpack result
  225. map[string]interface{}{
  226. "box": map[string]interface{}{"x": int32(55), "y": int32(65), "w": int32(33), "h": int32(69)},
  227. "features": []float32{0.031646, -0.800592, -1.101858, -0.354359, 0.656587},
  228. },
  229. map[string]interface{}{
  230. "box": map[string]interface{}{"x": int32(987), "y": int32(66), "w": int32(66), "h": int32(55)},
  231. "features": []float32{0.354359, 0.656587, -0.327047, 0.198284, -2.142494, 0.760160, 1.680131},
  232. },
  233. }},
  234. iresult: map[string]interface{}{
  235. "feature": []map[string]interface{}{
  236. {
  237. "box": map[string]interface{}{"x": int64(55), "y": int64(65), "w": int64(33), "h": int64(69)},
  238. "features": []float64{float64(float32(0.031646)), float64(float32(-0.800592)), float64(float32(-1.101858)), float64(float32(-0.354359)), float64(float32(0.656587))},
  239. },
  240. {
  241. "box": map[string]interface{}{"x": int64(987), "y": int64(66), "w": int64(66), "h": int64(55)},
  242. "features": []float64{float64(float32(0.354359)), float64(float32(0.656587)), float64(float32(-0.327047)), float64(float32(0.198284)), float64(float32(-2.142494)), float64(float32(0.760160)), float64(float32(1.680131))},
  243. },
  244. },
  245. },
  246. jreturn: []byte(`{"feature":[{"box":{"x":55,"y":65,"w":33,"h":69},"features":[0.031646, -0.800592, -1.101858, -0.354359, 0.656587]},{"box":{"x":987,"y":66,"w":66,"h":55},"features":[0.354359, 0.656587, -0.327047, 0.198284, -2.142494, 0.760160, 1.680131]}]}`),
  247. jresult: map[string]interface{}{
  248. "feature": []map[string]interface{}{
  249. {
  250. "box": map[string]interface{}{"x": int64(55), "y": int64(65), "w": int64(33), "h": int64(69)},
  251. "features": []float64{0.031646, -0.800592, -1.101858, -0.354359, 0.656587},
  252. },
  253. {
  254. "box": map[string]interface{}{"x": int64(987), "y": int64(66), "w": int64(66), "h": int64(55)},
  255. "features": []float64{0.354359, 0.656587, -0.327047, 0.198284, -2.142494, 0.760160, 1.680131},
  256. },
  257. },
  258. },
  259. },
  260. //{
  261. // method: "get_similarity",
  262. // ireturn: float32(0.987),
  263. // iresult: float64(float32(0.987)),
  264. // jreturn: []byte(`{"response":0.987}`),
  265. // jresult: map[string]interface{}{
  266. // "response": 0.987,
  267. // },
  268. //},
  269. }
  270. for i, descriptor := range descriptors {
  271. for j, tt := range tests {
  272. r, err := descriptor.(interfaceDescriptor).ConvertReturn(tt.method, tt.ireturn)
  273. if !reflect.DeepEqual(tt.ierr, testx.Errstring(err)) {
  274. t.Errorf("%d.%d : interface error mismatch:\n exp=%s\n got=%s\n\n", i, j, tt.ierr, err)
  275. } else if tt.ierr == "" && !reflect.DeepEqual(tt.iresult, r) {
  276. t.Errorf("%d.%d \n\ninterface result mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", i, j, tt.iresult, r)
  277. }
  278. rj, err := descriptor.(jsonDescriptor).ConvertReturnJson(tt.method, tt.jreturn)
  279. if !reflect.DeepEqual(tt.jerr, testx.Errstring(err)) {
  280. t.Errorf("%d.%d : json error mismatch:\n exp=%s\n got=%s\n\n", i, j, tt.jerr, err)
  281. } else if tt.jerr == "" && !reflect.DeepEqual(tt.jresult, rj) {
  282. t.Errorf("%d.%d \n\njson result mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", i, j, tt.jresult, rj)
  283. }
  284. }
  285. }
  286. }