You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

449 lines
10 KiB

  1. package binary
  2. import (
  3. "bytes"
  4. "fmt"
  5. "reflect"
  6. "testing"
  7. "time"
  8. )
  9. type SimpleStruct struct {
  10. String string
  11. Bytes []byte
  12. Time time.Time
  13. }
  14. //-------------------------------------
  15. type Animal interface{}
  16. const (
  17. AnimalTypeCat = byte(0x01)
  18. AnimalTypeDog = byte(0x02)
  19. AnimalTypeSnake = byte(0x03)
  20. AnimalTypeViper = byte(0x04)
  21. )
  22. // Implements Animal
  23. type Cat struct {
  24. SimpleStruct
  25. }
  26. // Implements Animal
  27. type Dog struct {
  28. SimpleStruct
  29. }
  30. // Implements Animal
  31. type Snake []byte
  32. // Implements Animal
  33. type Viper struct {
  34. Bytes []byte
  35. }
  36. var _ = RegisterInterface(
  37. struct{ Animal }{},
  38. ConcreteType{Cat{}, AnimalTypeCat},
  39. ConcreteType{Dog{}, AnimalTypeDog},
  40. ConcreteType{Snake{}, AnimalTypeSnake},
  41. ConcreteType{&Viper{}, AnimalTypeViper},
  42. )
  43. func TestAnimalInterface(t *testing.T) {
  44. var foo Animal
  45. // Type of pointer to Animal
  46. rt := reflect.TypeOf(&foo)
  47. fmt.Printf("rt: %v\n", rt)
  48. // Type of Animal itself.
  49. // NOTE: normally this is acquired through other means
  50. // like introspecting on method signatures, or struct fields.
  51. rte := rt.Elem()
  52. fmt.Printf("rte: %v\n", rte)
  53. // Get a new pointer to the interface
  54. // NOTE: calling .Interface() is to get the actual value,
  55. // instead of reflection values.
  56. ptr := reflect.New(rte).Interface()
  57. fmt.Printf("ptr: %v", ptr)
  58. // Make a binary byteslice that represents a snake.
  59. snakeBytes := BinaryBytes(Snake([]byte("snake")))
  60. snakeReader := bytes.NewReader(snakeBytes)
  61. // Now you can read it.
  62. n, err := new(int64), new(error)
  63. it := *ReadBinary(ptr, snakeReader, n, err).(*Animal)
  64. fmt.Println(it, reflect.TypeOf(it))
  65. }
  66. //-------------------------------------
  67. type Constructor func() interface{}
  68. type Instantiator func() (o interface{}, ptr interface{})
  69. type Validator func(o interface{}, t *testing.T)
  70. type TestCase struct {
  71. Constructor
  72. Instantiator
  73. Validator
  74. }
  75. //-------------------------------------
  76. func constructBasic() interface{} {
  77. cat := Cat{
  78. SimpleStruct{
  79. String: "String",
  80. Bytes: []byte("Bytes"),
  81. Time: time.Unix(123, 0),
  82. },
  83. }
  84. return cat
  85. }
  86. func instantiateBasic() (interface{}, interface{}) {
  87. return Cat{}, &Cat{}
  88. }
  89. func validateBasic(o interface{}, t *testing.T) {
  90. cat := o.(Cat)
  91. if cat.String != "String" {
  92. t.Errorf("Expected cat.String == 'String', got %v", cat.String)
  93. }
  94. if string(cat.Bytes) != "Bytes" {
  95. t.Errorf("Expected cat.Bytes == 'Bytes', got %X", cat.Bytes)
  96. }
  97. if cat.Time.Unix() != 123 {
  98. t.Errorf("Expected cat.Time == 'Unix(123)', got %v", cat.Time)
  99. }
  100. }
  101. //-------------------------------------
  102. type NilTestStruct struct {
  103. IntPtr *int
  104. CatPtr *Cat
  105. Animal Animal
  106. }
  107. func constructNilTestStruct() interface{} {
  108. return NilTestStruct{}
  109. }
  110. func instantiateNilTestStruct() (interface{}, interface{}) {
  111. return NilTestStruct{}, &NilTestStruct{}
  112. }
  113. func validateNilTestStruct(o interface{}, t *testing.T) {
  114. nts := o.(NilTestStruct)
  115. if nts.IntPtr != nil {
  116. t.Errorf("Expected nts.IntPtr to be nil, got %v", nts.IntPtr)
  117. }
  118. if nts.CatPtr != nil {
  119. t.Errorf("Expected nts.CatPtr to be nil, got %v", nts.CatPtr)
  120. }
  121. if nts.Animal != nil {
  122. t.Errorf("Expected nts.Animal to be nil, got %v", nts.Animal)
  123. }
  124. }
  125. //-------------------------------------
  126. type ComplexStruct struct {
  127. Name string
  128. Animal Animal
  129. }
  130. func constructComplex() interface{} {
  131. c := ComplexStruct{
  132. Name: "Complex",
  133. Animal: constructBasic(),
  134. }
  135. return c
  136. }
  137. func instantiateComplex() (interface{}, interface{}) {
  138. return ComplexStruct{}, &ComplexStruct{}
  139. }
  140. func validateComplex(o interface{}, t *testing.T) {
  141. c2 := o.(ComplexStruct)
  142. if cat, ok := c2.Animal.(Cat); ok {
  143. validateBasic(cat, t)
  144. } else {
  145. t.Errorf("Expected c2.Animal to be of type cat, got %v", reflect.ValueOf(c2.Animal).Elem().Type())
  146. }
  147. }
  148. //-------------------------------------
  149. type ComplexStruct2 struct {
  150. Cat Cat
  151. Dog *Dog
  152. Snake Snake
  153. Snake2 *Snake
  154. Viper Viper
  155. Viper2 *Viper
  156. }
  157. func constructComplex2() interface{} {
  158. snake_ := Snake([]byte("hiss"))
  159. snakePtr_ := &snake_
  160. c := ComplexStruct2{
  161. Cat: Cat{
  162. SimpleStruct{
  163. String: "String",
  164. Bytes: []byte("Bytes"),
  165. },
  166. },
  167. Dog: &Dog{
  168. SimpleStruct{
  169. String: "Woof",
  170. Bytes: []byte("Bark"),
  171. },
  172. },
  173. Snake: Snake([]byte("hiss")),
  174. Snake2: snakePtr_,
  175. Viper: Viper{Bytes: []byte("hizz")},
  176. Viper2: &Viper{Bytes: []byte("hizz")},
  177. }
  178. return c
  179. }
  180. func instantiateComplex2() (interface{}, interface{}) {
  181. return ComplexStruct2{}, &ComplexStruct2{}
  182. }
  183. func validateComplex2(o interface{}, t *testing.T) {
  184. c2 := o.(ComplexStruct2)
  185. cat := c2.Cat
  186. if cat.String != "String" {
  187. t.Errorf("Expected cat.String == 'String', got %v", cat.String)
  188. }
  189. if string(cat.Bytes) != "Bytes" {
  190. t.Errorf("Expected cat.Bytes == 'Bytes', got %X", cat.Bytes)
  191. }
  192. dog := c2.Dog
  193. if dog.String != "Woof" {
  194. t.Errorf("Expected dog.String == 'Woof', got %v", dog.String)
  195. }
  196. if string(dog.Bytes) != "Bark" {
  197. t.Errorf("Expected dog.Bytes == 'Bark', got %X", dog.Bytes)
  198. }
  199. snake := c2.Snake
  200. if string(snake) != "hiss" {
  201. t.Errorf("Expected string(snake) == 'hiss', got %v", string(snake))
  202. }
  203. snake2 := c2.Snake2
  204. if string(*snake2) != "hiss" {
  205. t.Errorf("Expected string(snake2) == 'hiss', got %v", string(*snake2))
  206. }
  207. viper := c2.Viper
  208. if string(viper.Bytes) != "hizz" {
  209. t.Errorf("Expected string(viper.Bytes) == 'hizz', got %v", string(viper.Bytes))
  210. }
  211. viper2 := c2.Viper2
  212. if string(viper2.Bytes) != "hizz" {
  213. t.Errorf("Expected string(viper2.Bytes) == 'hizz', got %v", string(viper2.Bytes))
  214. }
  215. }
  216. //-------------------------------------
  217. type ComplexStructArray struct {
  218. Animals []Animal
  219. }
  220. func constructComplexArray() interface{} {
  221. c := ComplexStructArray{
  222. Animals: []Animal{
  223. Cat{
  224. SimpleStruct{
  225. String: "String",
  226. Bytes: []byte("Bytes"),
  227. },
  228. },
  229. Dog{
  230. SimpleStruct{
  231. String: "Woof",
  232. Bytes: []byte("Bark"),
  233. },
  234. },
  235. Snake([]byte("hiss")),
  236. &Viper{
  237. Bytes: []byte("hizz"),
  238. },
  239. },
  240. }
  241. return c
  242. }
  243. func instantiateComplexArray() (interface{}, interface{}) {
  244. return ComplexStructArray{}, &ComplexStructArray{}
  245. }
  246. func validateComplexArray(o interface{}, t *testing.T) {
  247. c2 := o.(ComplexStructArray)
  248. if cat, ok := c2.Animals[0].(Cat); ok {
  249. if cat.String != "String" {
  250. t.Errorf("Expected cat.String == 'String', got %v", cat.String)
  251. }
  252. if string(cat.Bytes) != "Bytes" {
  253. t.Errorf("Expected cat.Bytes == 'Bytes', got %X", cat.Bytes)
  254. }
  255. } else {
  256. t.Errorf("Expected c2.Animals[0] to be of type cat, got %v", reflect.ValueOf(c2.Animals[0]).Elem().Type())
  257. }
  258. if dog, ok := c2.Animals[1].(Dog); ok {
  259. if dog.String != "Woof" {
  260. t.Errorf("Expected dog.String == 'Woof', got %v", dog.String)
  261. }
  262. if string(dog.Bytes) != "Bark" {
  263. t.Errorf("Expected dog.Bytes == 'Bark', got %X", dog.Bytes)
  264. }
  265. } else {
  266. t.Errorf("Expected c2.Animals[1] to be of type dog, got %v", reflect.ValueOf(c2.Animals[1]).Elem().Type())
  267. }
  268. if snake, ok := c2.Animals[2].(Snake); ok {
  269. if string(snake) != "hiss" {
  270. t.Errorf("Expected string(snake) == 'hiss', got %v", string(snake))
  271. }
  272. } else {
  273. t.Errorf("Expected c2.Animals[2] to be of type Snake, got %v", reflect.ValueOf(c2.Animals[2]).Elem().Type())
  274. }
  275. if viper, ok := c2.Animals[3].(*Viper); ok {
  276. if string(viper.Bytes) != "hizz" {
  277. t.Errorf("Expected string(viper.Bytes) == 'hizz', got %v", string(viper.Bytes))
  278. }
  279. } else {
  280. t.Errorf("Expected c2.Animals[3] to be of type *Viper, got %v", reflect.ValueOf(c2.Animals[3]).Elem().Type())
  281. }
  282. }
  283. //-----------------------------------------------------------------------------
  284. var testCases = []TestCase{}
  285. func init() {
  286. testCases = append(testCases, TestCase{constructBasic, instantiateBasic, validateBasic})
  287. testCases = append(testCases, TestCase{constructComplex, instantiateComplex, validateComplex})
  288. testCases = append(testCases, TestCase{constructComplex2, instantiateComplex2, validateComplex2})
  289. testCases = append(testCases, TestCase{constructComplexArray, instantiateComplexArray, validateComplexArray})
  290. testCases = append(testCases, TestCase{constructNilTestStruct, instantiateNilTestStruct, validateNilTestStruct})
  291. }
  292. func TestBinary(t *testing.T) {
  293. for i, testCase := range testCases {
  294. log.Info(fmt.Sprintf("Running test case %v", i))
  295. // Construct an object
  296. o := testCase.Constructor()
  297. // Write the object
  298. data := BinaryBytes(o)
  299. t.Logf("Binary: %X", data)
  300. instance, instancePtr := testCase.Instantiator()
  301. // Read onto a struct
  302. n, err := new(int64), new(error)
  303. res := ReadBinary(instance, bytes.NewReader(data), n, err)
  304. if *err != nil {
  305. t.Fatalf("Failed to read into instance: %v", *err)
  306. }
  307. // Validate object
  308. testCase.Validator(res, t)
  309. // Read onto a pointer
  310. n, err = new(int64), new(error)
  311. res = ReadBinary(instancePtr, bytes.NewReader(data), n, err)
  312. if *err != nil {
  313. t.Fatalf("Failed to read into instance: %v", *err)
  314. }
  315. if res != instancePtr {
  316. t.Errorf("Expected pointer to pass through")
  317. }
  318. // Validate object
  319. testCase.Validator(reflect.ValueOf(res).Elem().Interface(), t)
  320. }
  321. }
  322. func TestJSON(t *testing.T) {
  323. for i, testCase := range testCases {
  324. log.Info(fmt.Sprintf("Running test case %v", i))
  325. // Construct an object
  326. o := testCase.Constructor()
  327. // Write the object
  328. data := JSONBytes(o)
  329. t.Logf("JSON: %v", string(data))
  330. instance, instancePtr := testCase.Instantiator()
  331. // Read onto a struct
  332. err := new(error)
  333. res := ReadJSON(instance, data, err)
  334. if *err != nil {
  335. t.Fatalf("Failed to read cat: %v", *err)
  336. }
  337. // Validate object
  338. testCase.Validator(res, t)
  339. // Read onto a pointer
  340. res = ReadJSON(instancePtr, data, err)
  341. if *err != nil {
  342. t.Fatalf("Failed to read cat: %v", *err)
  343. }
  344. if res != instancePtr {
  345. t.Errorf("Expected pointer to pass through")
  346. }
  347. // Validate object
  348. testCase.Validator(reflect.ValueOf(res).Elem().Interface(), t)
  349. }
  350. }
  351. //------------------------------------------------------------------------------
  352. type Foo struct {
  353. FieldA string `json:"fieldA"` // json field name is "fieldA"
  354. FieldB string // json field name is "FieldB"
  355. fieldC string // not exported, not serialized.
  356. }
  357. func TestJSONFieldNames(t *testing.T) {
  358. for i := 0; i < 20; i++ { // Try to ensure deterministic success.
  359. foo := Foo{"a", "b", "c"}
  360. stringified := string(JSONBytes(foo))
  361. expected := `{"fieldA":"a","FieldB":"b"}`
  362. if stringified != expected {
  363. t.Fatalf("JSONFieldNames error: expected %v, got %v",
  364. expected, stringified)
  365. }
  366. }
  367. }