requiredexamplepb_test.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. // Protocol Buffers for Go with Gadgets
  2. //
  3. // Copyright (c) 2013, The GoGo Authors. All rights reserved.
  4. // http://github.com/gogo/protobuf
  5. //
  6. // Redistribution and use in source and binary forms, with or without
  7. // modification, are permitted provided that the following conditions are
  8. // met:
  9. //
  10. // * Redistributions of source code must retain the above copyright
  11. // notice, this list of conditions and the following disclaimer.
  12. // * Redistributions in binary form must reproduce the above
  13. // copyright notice, this list of conditions and the following disclaimer
  14. // in the documentation and/or other materials provided with the
  15. // distribution.
  16. //
  17. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  20. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  21. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  22. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  23. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  24. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  25. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  27. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. package required
  29. import (
  30. "github.com/gogo/protobuf/proto"
  31. "github.com/gogo/protobuf/test"
  32. "math/rand"
  33. "reflect"
  34. "strconv"
  35. "testing"
  36. "time"
  37. )
  38. func TestMarshalToErrorsWhenRequiredFieldIsNotPresent(t *testing.T) {
  39. data := RequiredExample{}
  40. buf, err := proto.Marshal(&data)
  41. if err == nil {
  42. t.Fatalf("err == nil; was %v instead", err)
  43. }
  44. if err.Error() != `proto: required field "theRequiredString" not set` {
  45. t.Fatalf(`err.Error() != "proto: required field "theRequiredString" not set"; was "%s" instead`, err.Error())
  46. }
  47. if len(buf) != 0 {
  48. t.Fatalf(`len(buf) != 0; was %d instead`, len(buf))
  49. }
  50. }
  51. func TestMarshalToSucceedsWhenRequiredFieldIsPresent(t *testing.T) {
  52. data := RequiredExample{
  53. TheRequiredString: proto.String("present"),
  54. }
  55. buf, err := proto.Marshal(&data)
  56. if err != nil {
  57. t.Fatalf("err != nil; was %v instead", err)
  58. }
  59. if len(buf) == 0 {
  60. t.Fatalf(`len(buf) == 0; expected nonzero`)
  61. }
  62. }
  63. func TestUnmarshalErrorsWhenRequiredFieldIsNotPresent(t *testing.T) {
  64. missingRequiredField := []byte{0x12, 0x8, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c}
  65. data := RequiredExample{}
  66. err := proto.Unmarshal(missingRequiredField, &data)
  67. if err == nil {
  68. t.Fatalf("err == nil; was %v instead", err)
  69. }
  70. if err.Error() != `proto: required field "theRequiredString" not set` {
  71. t.Fatalf(`err.Error() != "proto: required field "theRequiredString" not set"; was "%s" instead`, err.Error())
  72. }
  73. }
  74. func TestUnmarshalSucceedsWhenRequiredIsNotPresent(t *testing.T) {
  75. dataOut := RequiredExample{
  76. TheRequiredString: proto.String("present"),
  77. }
  78. encodedMessage, err := proto.Marshal(&dataOut)
  79. if err != nil {
  80. t.Fatalf("Unexpected error when marshalling dataOut: %v", err)
  81. }
  82. dataIn := RequiredExample{}
  83. err = proto.Unmarshal(encodedMessage, &dataIn)
  84. if err != nil {
  85. t.Fatalf("err != nil; was %v instead", err)
  86. }
  87. }
  88. func TestUnmarshalPopulatedOptionalFieldsAsRequiredSucceeds(t *testing.T) {
  89. r := rand.New(rand.NewSource(time.Now().UnixNano()))
  90. dataOut := test.NewPopulatedNidOptNative(r, true)
  91. encodedMessage, err := proto.Marshal(dataOut)
  92. if err != nil {
  93. t.Fatalf("Unexpected error when marshalling dataOut: %v", err)
  94. }
  95. dataIn := NidOptNative{}
  96. err = proto.Unmarshal(encodedMessage, &dataIn)
  97. if err != nil {
  98. t.Fatalf("err != nil; was %v instead", err)
  99. }
  100. }
  101. func TestUnmarshalPartiallyPopulatedOptionalFieldsFails(t *testing.T) {
  102. // Fill in all fields, then randomly remove one.
  103. dataOut := &test.NinOptNative{
  104. Field1: proto.Float64(0),
  105. Field2: proto.Float32(0),
  106. Field3: proto.Int32(0),
  107. Field4: proto.Int64(0),
  108. Field5: proto.Uint32(0),
  109. Field6: proto.Uint64(0),
  110. Field7: proto.Int32(0),
  111. Field8: proto.Int64(0),
  112. Field9: proto.Uint32(0),
  113. Field10: proto.Int32(0),
  114. Field11: proto.Uint64(0),
  115. Field12: proto.Int64(0),
  116. Field13: proto.Bool(false),
  117. Field14: proto.String("0"),
  118. Field15: []byte("0"),
  119. }
  120. r := rand.New(rand.NewSource(time.Now().UnixNano()))
  121. fieldName := "Field" + strconv.Itoa(r.Intn(15)+1)
  122. field := reflect.ValueOf(dataOut).Elem().FieldByName(fieldName)
  123. fieldType := field.Type()
  124. field.Set(reflect.Zero(fieldType))
  125. encodedMessage, err := proto.Marshal(dataOut)
  126. if err != nil {
  127. t.Fatalf("Unexpected error when marshalling dataOut: %v", err)
  128. }
  129. dataIn := NidOptNative{}
  130. err = proto.Unmarshal(encodedMessage, &dataIn)
  131. if err.Error() != `proto: required field "`+fieldName+`" not set` {
  132. t.Fatalf(`err.Error() != "proto: required field "`+fieldName+`" not set"; was "%s" instead`, err.Error())
  133. }
  134. }
  135. func TestMarshalFailsWithoutAllFieldsSet(t *testing.T) {
  136. r := rand.New(rand.NewSource(time.Now().UnixNano()))
  137. dataOut := NewPopulatedNinOptNative(r, true)
  138. fieldName := "Field" + strconv.Itoa(r.Intn(15)+1)
  139. field := reflect.ValueOf(dataOut).Elem().FieldByName(fieldName)
  140. fieldType := field.Type()
  141. field.Set(reflect.Zero(fieldType))
  142. encodedMessage, err := proto.Marshal(dataOut)
  143. if err.Error() != `proto: required field "`+fieldName+`" not set` {
  144. t.Fatalf(`err.Error() != "proto: required field "`+fieldName+`" not set"; was "%s" instead`, err.Error())
  145. }
  146. if len(encodedMessage) > 0 {
  147. t.Fatalf("Got some bytes from marshal, expected none.")
  148. }
  149. }
  150. func TestMissingFieldsOnRepeatedNestedTypes(t *testing.T) {
  151. r := rand.New(rand.NewSource(time.Now().UnixNano()))
  152. dataOut := &NestedNinOptNative{
  153. NestedNinOpts: []*NinOptNative{
  154. NewPopulatedNinOptNative(r, true),
  155. NewPopulatedNinOptNative(r, true),
  156. NewPopulatedNinOptNative(r, true),
  157. },
  158. }
  159. middle := dataOut.GetNestedNinOpts()[1]
  160. fieldName := "Field" + strconv.Itoa(r.Intn(15)+1)
  161. field := reflect.ValueOf(middle).Elem().FieldByName(fieldName)
  162. fieldType := field.Type()
  163. field.Set(reflect.Zero(fieldType))
  164. encodedMessage, err := proto.Marshal(dataOut)
  165. if err.Error() != `proto: required field "`+fieldName+`" not set` {
  166. t.Fatalf(`err.Error() != "proto: required field "`+fieldName+`" not set"; was "%s" instead`, err.Error())
  167. }
  168. if len(encodedMessage) > 0 {
  169. t.Fatalf("Got some bytes from marshal, expected none.")
  170. }
  171. }