2019-01-12 01:27:53 +03:00
|
|
|
/*
|
|
|
|
NAME
|
|
|
|
amf_test.go
|
|
|
|
|
|
|
|
DESCRIPTION
|
2019-01-12 06:16:21 +03:00
|
|
|
AMF test suite.
|
2019-01-12 01:27:53 +03:00
|
|
|
|
|
|
|
AUTHORS
|
|
|
|
Saxon Nelson-Milton <saxon@ausocean.org>
|
|
|
|
Dan Kortschak <dan@ausocean.org>
|
|
|
|
Alan Noble <alan@ausocean.org>
|
|
|
|
|
|
|
|
LICENSE
|
|
|
|
amf_test.go is Copyright (C) 2017-2019 the Australian Ocean Lab (AusOcean)
|
|
|
|
|
|
|
|
It is free software: you can redistribute it and/or modify them
|
|
|
|
under the terms of the GNU General Public License as published by the
|
|
|
|
Free Software Foundation, either version 3 of the License, or (at your
|
|
|
|
option) any later version.
|
|
|
|
|
|
|
|
It is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
|
|
for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with revid in gpl.txt. If not, see http://www.gnu.org/licenses.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package amf
|
|
|
|
|
|
|
|
import (
|
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
2019-01-12 06:16:21 +03:00
|
|
|
// Test data.
|
|
|
|
var testStrings = [...]string{
|
|
|
|
"",
|
|
|
|
"foo",
|
|
|
|
"bar",
|
|
|
|
"bazz",
|
|
|
|
}
|
|
|
|
|
|
|
|
var testNumbers = [...]int32{
|
|
|
|
0,
|
|
|
|
1,
|
|
|
|
0xababab,
|
|
|
|
0xffffff,
|
|
|
|
}
|
|
|
|
|
|
|
|
// TestSanity checks that we haven't accidentally changed constants.
|
|
|
|
func TestSanity(t *testing.T) {
|
|
|
|
if TypeObjectEnd != 0x09 {
|
|
|
|
t.Errorf("TypeObjectEnd has wrong value; got %d, expected %d", TypeObjectEnd, 0x09)
|
2019-01-12 01:27:53 +03:00
|
|
|
}
|
2019-01-12 06:16:21 +03:00
|
|
|
}
|
2019-01-12 01:27:53 +03:00
|
|
|
|
2019-01-12 06:16:21 +03:00
|
|
|
// TestStrings tests string encoding and decoding.
|
|
|
|
func TestStrings(t *testing.T) {
|
2019-01-12 01:27:53 +03:00
|
|
|
for _, s := range testStrings {
|
2019-01-12 06:16:21 +03:00
|
|
|
// Short string encoding is as follows:
|
2019-01-12 01:27:53 +03:00
|
|
|
// enc[0] = data type (typeString)
|
|
|
|
// end[1:3] = size
|
|
|
|
// enc[3:] = data
|
|
|
|
buf := make([]byte, len(s)+5)
|
2019-01-12 06:48:50 +03:00
|
|
|
_, err := EncodeString(buf, s)
|
|
|
|
if err != nil {
|
2019-01-12 01:27:53 +03:00
|
|
|
t.Errorf("EncodeString failed")
|
|
|
|
}
|
|
|
|
if buf[0] != typeString {
|
|
|
|
t.Errorf("Expected typeString, got %v", buf[0])
|
|
|
|
}
|
|
|
|
ds := DecodeString(buf[1:])
|
|
|
|
if s != ds {
|
|
|
|
t.Errorf("DecodeString did not produce original string, got %v", ds)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TestNumbers tests 24-bit encoding and encoding.
|
|
|
|
// We don't test the others as they are just wrappers for standard functions in encoding/binary.
|
|
|
|
func TestNumbers(t *testing.T) {
|
|
|
|
for _, n := range testNumbers {
|
|
|
|
buf := make([]byte, 4) // NB: encoder requires an extra byte for some reason
|
2019-01-12 06:48:50 +03:00
|
|
|
_, err := EncodeInt24(buf, n)
|
|
|
|
if err != nil {
|
2019-01-12 01:27:53 +03:00
|
|
|
t.Errorf("EncodeInt24 failed")
|
|
|
|
}
|
|
|
|
dn := int32(DecodeInt24(buf))
|
|
|
|
if n != dn {
|
2019-01-12 08:40:09 +03:00
|
|
|
t.Errorf("DecodeInt24 did not produce original Number, got %v", dn)
|
2019-01-12 01:27:53 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-01-12 06:16:21 +03:00
|
|
|
|
2019-01-13 07:54:38 +03:00
|
|
|
/*
|
2019-01-12 06:16:21 +03:00
|
|
|
// TestProperties tests encoding and decoding of properties.
|
|
|
|
func TestProperties(t *testing.T) {
|
|
|
|
var buf [1024]byte
|
|
|
|
|
2019-01-12 08:40:09 +03:00
|
|
|
// Encode/decode Number properties.
|
2019-01-12 06:16:21 +03:00
|
|
|
enc := buf[:]
|
2019-01-12 06:48:50 +03:00
|
|
|
var err error
|
2019-01-12 06:16:21 +03:00
|
|
|
for i, _ := range testNumbers {
|
2019-01-13 00:21:35 +03:00
|
|
|
enc, err = EncodeProperty(&Property{Type: typeNumber, Number: float64(testNumbers[i])}, enc)
|
2019-01-12 06:48:50 +03:00
|
|
|
if err != nil {
|
2019-01-13 00:21:35 +03:00
|
|
|
t.Errorf("EncodeProperty of Number failed")
|
2019-01-12 06:16:21 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2019-01-12 07:25:12 +03:00
|
|
|
|
2019-01-12 06:16:21 +03:00
|
|
|
prop := Property{}
|
|
|
|
dec := buf[:]
|
|
|
|
for i, _ := range testNumbers {
|
2019-01-13 00:21:35 +03:00
|
|
|
n, err := DecodeProperty(&prop, dec, false)
|
2019-01-12 07:25:12 +03:00
|
|
|
if err != nil {
|
2019-01-13 00:21:35 +03:00
|
|
|
t.Errorf("DecodeProperty of Number failed")
|
2019-01-12 06:16:21 +03:00
|
|
|
}
|
2019-01-12 08:40:09 +03:00
|
|
|
if int32(prop.Number) != testNumbers[i] {
|
2019-01-13 00:21:35 +03:00
|
|
|
t.Errorf("EncodeProperty/DecodeProperty returned wrong Number; got %v, expected %v", int32(prop.Number), testNumbers[i])
|
2019-01-12 06:16:21 +03:00
|
|
|
}
|
|
|
|
dec = dec[n:]
|
|
|
|
}
|
|
|
|
|
|
|
|
// Encode/decode string properties.
|
|
|
|
enc = buf[:]
|
|
|
|
for i, _ := range testStrings {
|
2019-01-13 00:21:35 +03:00
|
|
|
enc, err = EncodeProperty(&Property{Type: typeString, String: testStrings[i]}, enc)
|
2019-01-12 06:48:50 +03:00
|
|
|
if err != nil {
|
2019-01-13 00:21:35 +03:00
|
|
|
t.Errorf("EncodeProperty of string failed")
|
2019-01-12 06:16:21 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
prop = Property{}
|
|
|
|
dec = buf[:]
|
|
|
|
for i, _ := range testStrings {
|
2019-01-13 00:21:35 +03:00
|
|
|
n, err := DecodeProperty(&prop, dec, false)
|
2019-01-12 07:25:12 +03:00
|
|
|
if err != nil {
|
2019-01-13 00:21:35 +03:00
|
|
|
t.Errorf("DecodeProperty of string failed")
|
2019-01-12 06:16:21 +03:00
|
|
|
}
|
2019-01-12 08:40:09 +03:00
|
|
|
if prop.String != testStrings[i] {
|
2019-01-13 00:21:35 +03:00
|
|
|
t.Errorf("EncodeProperty/DecodeProperty returned wrong string; got %s, expected %s", prop.String, testStrings[i])
|
2019-01-12 06:16:21 +03:00
|
|
|
}
|
|
|
|
dec = dec[n:]
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2019-01-13 07:54:38 +03:00
|
|
|
*/
|
2019-01-12 06:16:21 +03:00
|
|
|
|
|
|
|
// TestObject tests encoding and decoding of objects.
|
|
|
|
func TestObject(t *testing.T) {
|
|
|
|
var buf [1024]byte
|
|
|
|
|
2019-01-12 08:40:09 +03:00
|
|
|
// Construct a simple object that has one property, the Number 42.
|
|
|
|
prop1 := Property{Type: typeNumber, Number: 42}
|
2019-01-12 06:16:21 +03:00
|
|
|
obj1 := Object{}
|
2019-01-12 10:34:04 +03:00
|
|
|
obj1.Properties = append(obj1.Properties, prop1)
|
2019-01-12 06:16:21 +03:00
|
|
|
|
|
|
|
// Encode it
|
|
|
|
enc := buf[:]
|
2019-01-12 06:48:50 +03:00
|
|
|
var err error
|
|
|
|
enc, err = Encode(&obj1, enc)
|
|
|
|
if err != nil {
|
2019-01-12 06:16:21 +03:00
|
|
|
t.Errorf("Encode of object failed")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check the encoding
|
|
|
|
if uint8(buf[0]) != TypeObject {
|
|
|
|
t.Errorf("Encoded wrong type; expected %d, got %v", TypeObject, uint8(buf[0]))
|
|
|
|
}
|
|
|
|
if uint8(buf[1]) != typeNumber {
|
|
|
|
t.Errorf("Encoded wrong type; expected %d, got %v", typeNumber, uint8(buf[0]))
|
|
|
|
}
|
|
|
|
num := DecodeNumber(buf[2:10])
|
|
|
|
if num != 42 {
|
2019-01-12 08:40:09 +03:00
|
|
|
t.Errorf("Encoded wrong Number")
|
2019-01-12 06:16:21 +03:00
|
|
|
}
|
|
|
|
end := int32(DecodeInt24(buf[10:13]))
|
|
|
|
if end != TypeObjectEnd {
|
|
|
|
t.Errorf("Did not encode TypeObjectEnd")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Decode it
|
|
|
|
dec := buf[1:]
|
|
|
|
var dobj1 Object
|
2019-01-12 07:25:12 +03:00
|
|
|
_, err = Decode(&dobj1, dec, false)
|
|
|
|
if err != nil {
|
2019-01-12 06:16:21 +03:00
|
|
|
t.Errorf("Decode of object failed")
|
|
|
|
}
|
|
|
|
|
2019-01-13 07:54:38 +03:00
|
|
|
// Change the object's property to a named boolean.
|
|
|
|
obj1.Properties[0].Name = "on"
|
2019-01-12 10:34:04 +03:00
|
|
|
obj1.Properties[0].Type = typeBoolean
|
|
|
|
obj1.Properties[0].Number = 1
|
2019-01-12 10:09:32 +03:00
|
|
|
|
|
|
|
// Re-encode it
|
|
|
|
enc = buf[:]
|
|
|
|
enc, err = Encode(&obj1, enc)
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("Encode of object failed")
|
|
|
|
}
|
|
|
|
|
2019-01-13 07:54:38 +03:00
|
|
|
// Decode it, this time with named set to true.
|
2019-01-12 10:09:32 +03:00
|
|
|
dec = buf[1:]
|
2019-01-13 07:54:38 +03:00
|
|
|
_, err = Decode(&dobj1, dec, true)
|
2019-01-12 10:09:32 +03:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("Decode of object failed with error: %v", err)
|
|
|
|
}
|
2019-01-12 10:34:04 +03:00
|
|
|
if dobj1.Properties[0].Number != 1 {
|
2019-01-12 10:09:32 +03:00
|
|
|
t.Errorf("Decoded wrong boolean value")
|
|
|
|
}
|
|
|
|
|
2019-01-13 04:39:06 +03:00
|
|
|
// Construct a more complicated object that includes a nested object.
|
2019-01-12 06:16:21 +03:00
|
|
|
var obj2 Object
|
|
|
|
for i, _ := range testStrings {
|
2019-01-12 10:34:04 +03:00
|
|
|
obj2.Properties = append(obj2.Properties, Property{Type: typeString, String: testStrings[i]})
|
|
|
|
obj2.Properties = append(obj2.Properties, Property{Type: typeNumber, Number: float64(testNumbers[i])})
|
2019-01-12 06:16:21 +03:00
|
|
|
}
|
2019-01-13 04:39:06 +03:00
|
|
|
obj2.Properties = append(obj2.Properties, Property{Type: TypeObject, Object: obj1})
|
2019-01-12 10:34:04 +03:00
|
|
|
obj2.Properties = append(obj2.Properties, Property{Type: typeBoolean, Number: 1})
|
2019-01-12 06:16:21 +03:00
|
|
|
|
2019-01-13 04:39:06 +03:00
|
|
|
// Retrieve nested object
|
|
|
|
obj, err := obj2.ObjectProperty("", 8)
|
|
|
|
if err != err {
|
|
|
|
t.Errorf("Failed to retrieve object")
|
|
|
|
}
|
|
|
|
if len(obj.Properties) < 1 {
|
|
|
|
t.Errorf("Properties missing for nested object")
|
|
|
|
}
|
|
|
|
if obj.Properties[0].Type != typeBoolean {
|
|
|
|
t.Errorf("Wrong property type for nested object")
|
|
|
|
}
|
|
|
|
|
2019-01-12 06:16:21 +03:00
|
|
|
// Encode it.
|
|
|
|
enc = buf[:]
|
2019-01-12 06:48:50 +03:00
|
|
|
enc, err = Encode(&obj2, enc)
|
|
|
|
if err != nil {
|
2019-01-12 06:16:21 +03:00
|
|
|
t.Errorf("Encode of object failed")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Decode it.
|
|
|
|
dec = buf[1:]
|
|
|
|
var dobj2 Object
|
2019-01-12 07:25:12 +03:00
|
|
|
_, err = Decode(&dobj2, dec, false)
|
|
|
|
if err != nil {
|
2019-01-12 10:09:32 +03:00
|
|
|
t.Errorf("Decode of object failed with error: %v", err)
|
2019-01-12 06:16:21 +03:00
|
|
|
}
|
2019-01-12 08:40:09 +03:00
|
|
|
|
|
|
|
// Find some properties that exist.
|
2019-01-13 00:39:54 +03:00
|
|
|
s, err := obj2.StringProperty("", 2)
|
2019-01-12 08:40:09 +03:00
|
|
|
if err != nil {
|
2019-01-13 04:39:06 +03:00
|
|
|
t.Errorf("StringProperty failed")
|
2019-01-12 08:40:09 +03:00
|
|
|
}
|
2019-01-13 00:39:54 +03:00
|
|
|
if s != "foo" {
|
2019-01-13 04:39:06 +03:00
|
|
|
t.Errorf("StringProperty returned wrong String")
|
2019-01-12 08:40:09 +03:00
|
|
|
}
|
2019-01-13 00:39:54 +03:00
|
|
|
n, err := obj2.NumberProperty("", 3)
|
2019-01-12 08:40:09 +03:00
|
|
|
if err != nil {
|
2019-01-13 04:39:06 +03:00
|
|
|
t.Errorf("NumberProperty failed")
|
2019-01-12 08:40:09 +03:00
|
|
|
}
|
2019-01-13 00:39:54 +03:00
|
|
|
if n != 1 {
|
2019-01-13 04:39:06 +03:00
|
|
|
t.Errorf("NumberProperty returned wrong Number")
|
|
|
|
}
|
|
|
|
obj, err = obj2.ObjectProperty("", 8)
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("ObjectProperty failed")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if obj.Properties[0].Type != typeBoolean {
|
|
|
|
t.Errorf("ObjectProperty returned object with wrong property")
|
2019-01-12 08:40:09 +03:00
|
|
|
}
|
2019-01-13 00:39:54 +03:00
|
|
|
prop, err := obj2.Property("", 9, typeBoolean)
|
2019-01-12 10:09:32 +03:00
|
|
|
if err != nil {
|
2019-01-13 04:39:06 +03:00
|
|
|
t.Errorf("Property failed")
|
2019-01-12 10:09:32 +03:00
|
|
|
return
|
|
|
|
}
|
2019-01-12 11:13:51 +03:00
|
|
|
if prop.Number != 1 {
|
2019-01-13 04:39:06 +03:00
|
|
|
t.Errorf("Property returned wrong Property")
|
2019-01-12 10:09:32 +03:00
|
|
|
}
|
2019-01-12 08:40:09 +03:00
|
|
|
|
|
|
|
// Try to find one that doesn't exist.
|
2019-01-13 00:39:54 +03:00
|
|
|
prop, err = obj2.Property("", 10, TypeObject)
|
2019-01-12 08:40:09 +03:00
|
|
|
if err != ErrPropertyNotFound {
|
2019-01-13 00:39:54 +03:00
|
|
|
t.Errorf("Property(10) failed")
|
2019-01-12 08:40:09 +03:00
|
|
|
}
|
2019-01-12 06:16:21 +03:00
|
|
|
}
|