You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ac...@apache.org on 2018/07/03 22:14:18 UTC
[89/89] [abbrv] qpid-proton git commit: Merge tag '0.23.0' into go1
Merge tag '0.23.0' into go1
Release 0.23.0
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/6f579de7
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/6f579de7
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/6f579de7
Branch: refs/heads/go1
Commit: 6f579de70413d076bd38252239c9d2338fdff8df
Parents: 6f79999 4fe5040
Author: Alan Conway <ac...@redhat.com>
Authored: Tue Jul 3 18:11:34 2018 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Tue Jul 3 18:11:34 2018 -0400
----------------------------------------------------------------------
amqp/message.go | 11 ++++++++++-
amqp/message_test.go | 32 ++++++++++++++++++++++++--------
readme-go-get.md | 4 ++--
3 files changed, 36 insertions(+), 11 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6f579de7/amqp/message.go
----------------------------------------------------------------------
diff --cc amqp/message.go
index 389fa37,0000000..e514b26
mode 100644,000000..100644
--- a/amqp/message.go
+++ b/amqp/message.go
@@@ -1,420 -1,0 +1,429 @@@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+package amqp
+
+// #include <proton/codec.h>
+// #include <proton/types.h>
+// #include <proton/message.h>
+// #include <stdlib.h>
+//
+// /* Helper for setting message string fields */
+// typedef int (*set_fn)(pn_message_t*, const char*);
+// int msg_set_str(pn_message_t* m, char* s, set_fn set) {
+// int result = set(m, s);
+// free(s);
+// return result;
+// }
+//
+import "C"
+
+import (
+ "fmt"
+ "runtime"
+ "time"
++ "unsafe"
+)
+
+// Message is the interface to an AMQP message.
+type Message interface {
+ // Durable indicates that any parties taking responsibility
+ // for the message must durably store the content.
+ Durable() bool
+ SetDurable(bool)
+
+ // Priority impacts ordering guarantees. Within a
+ // given ordered context, higher priority messages may jump ahead of
+ // lower priority messages.
+ Priority() uint8
+ SetPriority(uint8)
+
+ // TTL or Time To Live, a message it may be dropped after this duration
+ TTL() time.Duration
+ SetTTL(time.Duration)
+
+ // FirstAcquirer indicates
+ // that the recipient of the message is the first recipient to acquire
+ // the message, i.e. there have been no failed delivery attempts to
+ // other acquirers. Note that this does not mean the message has not
+ // been delivered to, but not acquired, by other recipients.
+ FirstAcquirer() bool
+ SetFirstAcquirer(bool)
+
+ // DeliveryCount tracks how many attempts have been made to
+ // delivery a message.
+ DeliveryCount() uint32
+ SetDeliveryCount(uint32)
+
+ // MessageId provides a unique identifier for a message.
+ // it can be an a string, an unsigned long, a uuid or a
+ // binary value.
+ MessageId() interface{}
+ SetMessageId(interface{})
+
+ UserId() string
+ SetUserId(string)
+
+ Address() string
+ SetAddress(string)
+
+ Subject() string
+ SetSubject(string)
+
+ ReplyTo() string
+ SetReplyTo(string)
+
+ // CorrelationId is set on correlated request and response messages. It can be
+ // an a string, an unsigned long, a uuid or a binary value.
+ CorrelationId() interface{}
+ SetCorrelationId(interface{})
+
+ ContentType() string
+ SetContentType(string)
+
+ ContentEncoding() string
+ SetContentEncoding(string)
+
+ // ExpiryTime indicates an absolute time when the message may be dropped.
+ // A Zero time (i.e. t.isZero() == true) indicates a message never expires.
+ ExpiryTime() time.Time
+ SetExpiryTime(time.Time)
+
+ CreationTime() time.Time
+ SetCreationTime(time.Time)
+
+ GroupId() string
+ SetGroupId(string)
+
+ GroupSequence() int32
+ SetGroupSequence(int32)
+
+ ReplyToGroupId() string
+ SetReplyToGroupId(string)
+
+ // Property map set by the application to be carried with the message.
+ // Values must be simple types (not maps, lists or sequences)
+ ApplicationProperties() map[string]interface{}
+ SetApplicationProperties(map[string]interface{})
+
+ // Per-delivery annotations to provide delivery instructions.
+ // May be added or removed by intermediaries during delivery.
+ DeliveryAnnotations() map[AnnotationKey]interface{}
+ SetDeliveryAnnotations(map[AnnotationKey]interface{})
+
+ // Message annotations added as part of the bare message at creation, usually
+ // by an AMQP library. See ApplicationProperties() for adding application data.
+ MessageAnnotations() map[AnnotationKey]interface{}
+ SetMessageAnnotations(map[AnnotationKey]interface{})
+
+ // Inferred indicates how the message content
+ // is encoded into AMQP sections. If inferred is true then binary and
+ // list values in the body of the message will be encoded as AMQP DATA
+ // and AMQP SEQUENCE sections, respectively. If inferred is false,
+ // then all values in the body of the message will be encoded as AMQP
+ // VALUE sections regardless of their type.
+ Inferred() bool
+ SetInferred(bool)
+
+ // Marshal a Go value into the message body. See amqp.Marshal() for details.
+ Marshal(interface{})
+
+ // Unmarshal the message body into the value pointed to by v. See amqp.Unmarshal() for details.
+ Unmarshal(interface{})
+
+ // Body value resulting from the default unmarshaling of message body as interface{}
+ Body() interface{}
+
+ // Encode encodes the message as AMQP data. If buffer is non-nil and is large enough
+ // the message is encoded into it, otherwise a new buffer is created.
+ // Returns the buffer containing the message.
+ Encode(buffer []byte) ([]byte, error)
+
+ // Decode data into this message. Overwrites an existing message content.
+ Decode(buffer []byte) error
+
+ // Clear the message contents.
+ Clear()
+
+ // Copy the contents of another message to this one.
+ Copy(m Message) error
+
+ // Deprecated: use DeliveryAnnotations() for a more type-safe interface
+ Instructions() map[string]interface{}
+ SetInstructions(v map[string]interface{})
+
+ // Deprecated: use MessageAnnotations() for a more type-safe interface
+ Annotations() map[string]interface{}
+ SetAnnotations(v map[string]interface{})
+
+ // Deprecated: use ApplicationProperties() for a more type-safe interface
+ Properties() map[string]interface{}
+ SetProperties(v map[string]interface{})
++
++ // Human-readable string showing message contents and properties
++ String() string
+}
+
+type message struct{ pn *C.pn_message_t }
+
+func freeMessage(m *message) {
+ C.pn_message_free(m.pn)
+ m.pn = nil
+}
+
+// NewMessage creates a new message instance.
+func NewMessage() Message {
+ m := &message{C.pn_message()}
+ runtime.SetFinalizer(m, freeMessage)
+ return m
+}
+
+// NewMessageWith creates a message with value as the body. Equivalent to
+// m := NewMessage(); m.Marshal(body)
+func NewMessageWith(value interface{}) Message {
+ m := NewMessage()
+ m.Marshal(value)
+ return m
+}
+
+func (m *message) Clear() { C.pn_message_clear(m.pn) }
+
+func (m *message) Copy(x Message) error {
+ if data, err := x.Encode(nil); err == nil {
+ return m.Decode(data)
+ } else {
+ return err
+ }
+}
+
+// ==== message get functions
+
+func rewindGet(data *C.pn_data_t) (v interface{}) {
+ C.pn_data_rewind(data)
+ C.pn_data_next(data)
+ unmarshal(&v, data)
+ return v
+}
+
+func (m *message) Inferred() bool { return bool(C.pn_message_is_inferred(m.pn)) }
+func (m *message) Durable() bool { return bool(C.pn_message_is_durable(m.pn)) }
+func (m *message) Priority() uint8 { return uint8(C.pn_message_get_priority(m.pn)) }
+func (m *message) TTL() time.Duration {
+ return time.Duration(C.pn_message_get_ttl(m.pn)) * time.Millisecond
+}
+func (m *message) FirstAcquirer() bool { return bool(C.pn_message_is_first_acquirer(m.pn)) }
+func (m *message) DeliveryCount() uint32 { return uint32(C.pn_message_get_delivery_count(m.pn)) }
+func (m *message) MessageId() interface{} { return rewindGet(C.pn_message_id(m.pn)) }
+func (m *message) UserId() string { return goString(C.pn_message_get_user_id(m.pn)) }
+func (m *message) Address() string { return C.GoString(C.pn_message_get_address(m.pn)) }
+func (m *message) Subject() string { return C.GoString(C.pn_message_get_subject(m.pn)) }
+func (m *message) ReplyTo() string { return C.GoString(C.pn_message_get_reply_to(m.pn)) }
+func (m *message) CorrelationId() interface{} { return rewindGet(C.pn_message_correlation_id(m.pn)) }
+func (m *message) ContentType() string { return C.GoString(C.pn_message_get_content_type(m.pn)) }
+func (m *message) ContentEncoding() string { return C.GoString(C.pn_message_get_content_encoding(m.pn)) }
+
+func (m *message) ExpiryTime() time.Time {
+ return time.Unix(0, int64(time.Millisecond*time.Duration(C.pn_message_get_expiry_time(m.pn))))
+}
+func (m *message) CreationTime() time.Time {
+ return time.Unix(0, int64(time.Millisecond)*int64(C.pn_message_get_creation_time(m.pn)))
+}
+func (m *message) GroupId() string { return C.GoString(C.pn_message_get_group_id(m.pn)) }
+func (m *message) GroupSequence() int32 { return int32(C.pn_message_get_group_sequence(m.pn)) }
+func (m *message) ReplyToGroupId() string { return C.GoString(C.pn_message_get_reply_to_group_id(m.pn)) }
+
+func getAnnotations(data *C.pn_data_t) (v map[AnnotationKey]interface{}) {
+ if C.pn_data_size(data) > 0 {
+ C.pn_data_rewind(data)
+ C.pn_data_next(data)
+ unmarshal(&v, data)
+ }
+ return v
+}
+
+func (m *message) DeliveryAnnotations() map[AnnotationKey]interface{} {
+ return getAnnotations(C.pn_message_instructions(m.pn))
+}
+func (m *message) MessageAnnotations() map[AnnotationKey]interface{} {
+ return getAnnotations(C.pn_message_annotations(m.pn))
+}
+
+func (m *message) ApplicationProperties() map[string]interface{} {
+ var v map[string]interface{}
+ data := C.pn_message_properties(m.pn)
+ if C.pn_data_size(data) > 0 {
+ C.pn_data_rewind(data)
+ C.pn_data_next(data)
+ unmarshal(&v, data)
+ }
+ return v
+}
+
+// ==== message set methods
+
+func setData(v interface{}, data *C.pn_data_t) {
+ C.pn_data_clear(data)
+ marshal(v, data)
+}
+
+func (m *message) SetInferred(b bool) { C.pn_message_set_inferred(m.pn, C.bool(b)) }
+func (m *message) SetDurable(b bool) { C.pn_message_set_durable(m.pn, C.bool(b)) }
+func (m *message) SetPriority(b uint8) { C.pn_message_set_priority(m.pn, C.uint8_t(b)) }
+func (m *message) SetTTL(d time.Duration) {
+ C.pn_message_set_ttl(m.pn, C.pn_millis_t(d/time.Millisecond))
+}
+func (m *message) SetFirstAcquirer(b bool) { C.pn_message_set_first_acquirer(m.pn, C.bool(b)) }
+func (m *message) SetDeliveryCount(c uint32) { C.pn_message_set_delivery_count(m.pn, C.uint32_t(c)) }
+func (m *message) SetMessageId(id interface{}) { setData(id, C.pn_message_id(m.pn)) }
+func (m *message) SetUserId(s string) { C.pn_message_set_user_id(m.pn, pnBytes(([]byte)(s))) }
+func (m *message) SetAddress(s string) {
+ C.msg_set_str(m.pn, C.CString(s), C.set_fn(C.pn_message_set_address))
+}
+func (m *message) SetSubject(s string) {
+ C.msg_set_str(m.pn, C.CString(s), C.set_fn(C.pn_message_set_subject))
+}
+func (m *message) SetReplyTo(s string) {
+ C.msg_set_str(m.pn, C.CString(s), C.set_fn(C.pn_message_set_reply_to))
+}
+func (m *message) SetCorrelationId(c interface{}) { setData(c, C.pn_message_correlation_id(m.pn)) }
+func (m *message) SetContentType(s string) {
+ C.msg_set_str(m.pn, C.CString(s), C.set_fn(C.pn_message_set_content_type))
+}
+func (m *message) SetContentEncoding(s string) {
+ C.msg_set_str(m.pn, C.CString(s), C.set_fn(C.pn_message_set_content_encoding))
+}
+func (m *message) SetExpiryTime(t time.Time) { C.pn_message_set_expiry_time(m.pn, pnTime(t)) }
+func (m *message) SetCreationTime(t time.Time) { C.pn_message_set_creation_time(m.pn, pnTime(t)) }
+func (m *message) SetGroupId(s string) {
+ C.msg_set_str(m.pn, C.CString(s), C.set_fn(C.pn_message_set_group_id))
+}
+func (m *message) SetGroupSequence(s int32) {
+ C.pn_message_set_group_sequence(m.pn, C.pn_sequence_t(s))
+}
+func (m *message) SetReplyToGroupId(s string) {
+ C.msg_set_str(m.pn, C.CString(s), C.set_fn(C.pn_message_set_reply_to_group_id))
+}
+
+func (m *message) SetDeliveryAnnotations(v map[AnnotationKey]interface{}) {
+ setData(v, C.pn_message_instructions(m.pn))
+}
+func (m *message) SetMessageAnnotations(v map[AnnotationKey]interface{}) {
+ setData(v, C.pn_message_annotations(m.pn))
+}
+func (m *message) SetApplicationProperties(v map[string]interface{}) {
+ setData(v, C.pn_message_properties(m.pn))
+}
+
+// Marshal body from v
+func (m *message) Marshal(v interface{}) { clearMarshal(v, C.pn_message_body(m.pn)) }
+
+// Unmarshal body to v, which must be a pointer to a value. See amqp.Unmarshal
+func (m *message) Unmarshal(v interface{}) {
+ data := C.pn_message_body(m.pn)
+ if C.pn_data_size(data) > 0 {
+ C.pn_data_rewind(data)
+ C.pn_data_next(data)
+ unmarshal(v, data)
+ }
+ return
+}
+
+// Return the body value as an interface
+func (m *message) Body() (v interface{}) { m.Unmarshal(&v); return }
+
+func (m *message) Decode(data []byte) error {
+ m.Clear()
+ if len(data) == 0 {
+ return fmt.Errorf("empty buffer for decode")
+ }
+ if C.pn_message_decode(m.pn, cPtr(data), cLen(data)) < 0 {
+ return fmt.Errorf("decoding message: %s", PnError(C.pn_message_error(m.pn)))
+ }
+ return nil
+}
+
+func DecodeMessage(data []byte) (m Message, err error) {
+ m = NewMessage()
+ err = m.Decode(data)
+ return
+}
+
+func (m *message) Encode(buffer []byte) ([]byte, error) {
+ encode := func(buf []byte) ([]byte, error) {
+ len := cLen(buf)
+ result := C.pn_message_encode(m.pn, cPtr(buf), &len)
+ switch {
+ case result == C.PN_OVERFLOW:
+ return buf, overflow
+ case result < 0:
+ return buf, fmt.Errorf("cannot encode message: %s", PnErrorCode(result))
+ default:
+ return buf[:len], nil
+ }
+ }
+ return encodeGrow(buffer, encode)
+}
+
+// TODO aconway 2015-09-14: Multi-section messages.
+
- // TODO aconway 2016-09-09: Message.String() use inspect.
++func (m *message) String() string {
++ str := C.pn_string(C.CString(""))
++ defer C.pn_free(unsafe.Pointer(str))
++ C.pn_inspect(unsafe.Pointer(m.pn), str)
++ return C.GoString(C.pn_string_get(str))
++}
+
+// ==== Deprecated functions
+func oldGetAnnotations(data *C.pn_data_t) (v map[string]interface{}) {
+ if C.pn_data_size(data) > 0 {
+ C.pn_data_rewind(data)
+ C.pn_data_next(data)
+ unmarshal(&v, data)
+ }
+ return v
+}
+
+func (m *message) Instructions() map[string]interface{} {
+ return oldGetAnnotations(C.pn_message_instructions(m.pn))
+}
+func (m *message) Annotations() map[string]interface{} {
+ return oldGetAnnotations(C.pn_message_annotations(m.pn))
+}
+func (m *message) Properties() map[string]interface{} {
+ return oldGetAnnotations(C.pn_message_properties(m.pn))
+}
+
+// Convert old string-keyed annotations to an AnnotationKey map
+func fixAnnotations(old map[string]interface{}) (annotations map[AnnotationKey]interface{}) {
+ annotations = make(map[AnnotationKey]interface{})
+ for k, v := range old {
+ annotations[AnnotationKeyString(k)] = v
+ }
+ return
+}
+
+func (m *message) SetInstructions(v map[string]interface{}) {
+ setData(fixAnnotations(v), C.pn_message_instructions(m.pn))
+}
+func (m *message) SetAnnotations(v map[string]interface{}) {
+ setData(fixAnnotations(v), C.pn_message_annotations(m.pn))
+}
+func (m *message) SetProperties(v map[string]interface{}) {
+ setData(fixAnnotations(v), C.pn_message_properties(m.pn))
+}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6f579de7/amqp/message_test.go
----------------------------------------------------------------------
diff --cc amqp/message_test.go
index 3585dd8,0000000..663e82f
mode 100644,000000..100644
--- a/amqp/message_test.go
+++ b/amqp/message_test.go
@@@ -1,201 -1,0 +1,217 @@@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+package amqp
+
+import (
+ "testing"
+ "time"
+)
+
+func roundTrip(m Message) error {
- buffer, err := m.Encode(nil)
- if err != nil {
- return err
- }
- m2, err := DecodeMessage(buffer)
- if err != nil {
- return err
++ var err error
++ if buffer, err := m.Encode(nil); err == nil {
++ if m2, err := DecodeMessage(buffer); err == nil {
++ if err = checkEqual(m, m2); err == nil {
++ err = checkEqual(m.String(), m2.String())
++ }
++ }
+ }
- return checkEqual(m, m2)
++ return err
+}
+
+func TestDefaultMessage(t *testing.T) {
+ m := NewMessage()
+ // Check defaults
+ for _, data := range [][]interface{}{
+ {m.Inferred(), false},
+ {m.Durable(), false},
+ {m.Priority(), uint8(4)},
+ {m.TTL(), time.Duration(0)},
+ {m.UserId(), ""},
+ {m.Address(), ""},
+ {m.Subject(), ""},
+ {m.ReplyTo(), ""},
+ {m.ContentType(), ""},
+ {m.ContentEncoding(), ""},
+ {m.GroupId(), ""},
+ {m.GroupSequence(), int32(0)},
+ {m.ReplyToGroupId(), ""},
+ {m.MessageId(), nil},
+ {m.CorrelationId(), nil},
+ {m.DeliveryAnnotations(), map[AnnotationKey]interface{}(nil)},
+ {m.MessageAnnotations(), map[AnnotationKey]interface{}(nil)},
+ {m.ApplicationProperties(), map[string]interface{}(nil)},
+
+ // Deprecated
+ {m.Instructions(), map[string]interface{}(nil)},
+ {m.Annotations(), map[string]interface{}(nil)},
+ {m.Properties(), map[string]interface{}(nil)},
+ {m.Body(), nil},
+ } {
+ if err := checkEqual(data[0], data[1]); err != nil {
+ t.Error(err)
+ }
+ }
+ if err := roundTrip(m); err != nil {
+ t.Error(err)
+ }
++ if err := checkEqual("Message{}", m.String()); err != nil {
++ t.Error(err)
++ }
++}
++
++func TestMessageString(t *testing.T) {
++ m := NewMessageWith("hello")
++ m.SetInferred(false)
++ m.SetUserId("user")
++ m.SetDeliveryAnnotations(map[AnnotationKey]interface{}{AnnotationKeySymbol("instructions"): "foo"})
++ m.SetMessageAnnotations(map[AnnotationKey]interface{}{AnnotationKeySymbol("annotations"): "bar"})
++ m.SetApplicationProperties(map[string]interface{}{"int": int32(32)})
++ msgstr := `Message{user_id="user", instructions={:instructions="foo"}, annotations={:annotations="bar"}, properties={"int"=32}, body="hello"}`
++ if err := checkEqual(msgstr, m.String()); err != nil {
++ t.Error(err)
++ }
+}
+
+func TestMessageRoundTrip(t *testing.T) {
+ m := NewMessage()
+ m.SetInferred(false)
+ m.SetDurable(true)
+ m.SetPriority(42)
+ m.SetTTL(0)
+ m.SetUserId("user")
+ m.SetAddress("address")
+ m.SetSubject("subject")
+ m.SetReplyTo("replyto")
+ m.SetContentType("content")
+ m.SetContentEncoding("encoding")
+ m.SetGroupId("group")
+ m.SetGroupSequence(42)
+ m.SetReplyToGroupId("replytogroup")
+ m.SetMessageId("id")
+ m.SetCorrelationId("correlation")
+ m.SetDeliveryAnnotations(map[AnnotationKey]interface{}{AnnotationKeySymbol("instructions"): "foo"})
+ m.SetMessageAnnotations(map[AnnotationKey]interface{}{AnnotationKeySymbol("annotations"): "bar"})
+ m.SetApplicationProperties(map[string]interface{}{"int": int32(32), "bool": true})
+ m.Marshal("hello")
+
+ for _, data := range [][]interface{}{
+ {m.Inferred(), false},
+ {m.Durable(), true},
+ {m.Priority(), uint8(42)},
+ {m.TTL(), time.Duration(0)},
+ {m.UserId(), "user"},
+ {m.Address(), "address"},
+ {m.Subject(), "subject"},
+ {m.ReplyTo(), "replyto"},
+ {m.ContentType(), "content"},
+ {m.ContentEncoding(), "encoding"},
+ {m.GroupId(), "group"},
+ {m.GroupSequence(), int32(42)},
+ {m.ReplyToGroupId(), "replytogroup"},
+ {m.MessageId(), "id"},
+ {m.CorrelationId(), "correlation"},
+
+ {m.DeliveryAnnotations(), map[AnnotationKey]interface{}{AnnotationKeySymbol("instructions"): "foo"}},
+ {m.MessageAnnotations(), map[AnnotationKey]interface{}{AnnotationKeySymbol("annotations"): "bar"}},
+ {m.ApplicationProperties(), map[string]interface{}{"int": int32(32), "bool": true}},
+ {m.Body(), "hello"},
+
+ // Deprecated
+ {m.Instructions(), map[string]interface{}{"instructions": "foo"}},
+ {m.Annotations(), map[string]interface{}{"annotations": "bar"}},
+ } {
+ if err := checkEqual(data[0], data[1]); err != nil {
+ t.Error(err)
+ }
+ }
+ if err := roundTrip(m); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestDeprecated(t *testing.T) {
+ m := NewMessage()
+
+ m.SetInstructions(map[string]interface{}{"instructions": "foo"})
+ m.SetAnnotations(map[string]interface{}{"annotations": "bar"})
+ m.SetProperties(map[string]interface{}{"int": int32(32), "bool": true})
+
+ for _, data := range [][]interface{}{
+ {m.DeliveryAnnotations(), map[AnnotationKey]interface{}{AnnotationKeySymbol("instructions"): "foo"}},
+ {m.MessageAnnotations(), map[AnnotationKey]interface{}{AnnotationKeySymbol("annotations"): "bar"}},
+ {m.ApplicationProperties(), map[string]interface{}{"int": int32(32), "bool": true}},
+
+ {m.Instructions(), map[string]interface{}{"instructions": "foo"}},
+ {m.Annotations(), map[string]interface{}{"annotations": "bar"}},
+ {m.Properties(), map[string]interface{}{"int": int32(32), "bool": true}},
+ } {
+ if err := checkEqual(data[0], data[1]); err != nil {
+ t.Error(err)
+ }
+ }
+ if err := roundTrip(m); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestMessageBodyTypes(t *testing.T) {
+ var s string
+ var body interface{}
+ var i int64
+
+ m := NewMessageWith(int64(42))
+ m.Unmarshal(&body)
+ m.Unmarshal(&i)
+ if err := checkEqual(body.(int64), int64(42)); err != nil {
+ t.Error(err)
+ }
+ if err := checkEqual(i, int64(42)); err != nil {
+ t.Error(err)
+ }
+
+ m = NewMessageWith("hello")
+ m.Unmarshal(&s)
+ m.Unmarshal(&body)
+ if err := checkEqual(s, "hello"); err != nil {
+ t.Error(err)
+ }
+ if err := checkEqual(body.(string), "hello"); err != nil {
+ t.Error(err)
+ }
+ if err := roundTrip(m); err != nil {
+ t.Error(err)
+ }
+
+ m = NewMessageWith(Binary("bin"))
+ m.Unmarshal(&s)
+ m.Unmarshal(&body)
+ if err := checkEqual(body.(Binary), Binary("bin")); err != nil {
+ t.Error(err)
+ }
+ if err := checkEqual(s, "bin"); err != nil {
+ t.Error(err)
+ }
+ if err := roundTrip(m); err != nil {
+ t.Error(err)
+ }
+
+ // TODO aconway 2015-09-08: array etc.
+}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6f579de7/readme-go-get.md
----------------------------------------------------------------------
diff --cc readme-go-get.md
index c59561f,0000000..09dde96
mode 100644,000000..100644
--- a/readme-go-get.md
+++ b/readme-go-get.md
@@@ -1,19 -1,0 +1,19 @@@
+The go-only subtree of proton is maintained on the branch `go1` for the `go get`
+command. `go1` is special to the `go get` command, it will use that branch
+rather than `master` when it is present.
+
+Created with:
+
- git subtree split --prefix=proton-c/bindings/go/src/qpid.apache.org -b go1
++ git subtree split --prefix=go/src/qpid.apache.org -b go1
+
+Update with:
+
+ git checkout go1
+ git pull
- git merge -s recursive -Xsubtree=proton-c/bindings/go/src/qpid.apache.org master
++ git merge -s recursive -Xsubtree=go/src/qpid.apache.org master
+
+To see the branch description: `git config branch.go1.description`
+
+NOTE: when updating the branch, you should also visit the doc pages at
+https://godoc.org/?q=qpid.apache.org and click "Refresh now" at the bottom of
+the page
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org