// Protocol Buffers for Go with Gadgets // // Copyright (c) 2013, The GoGo Authors. All rights reserved. // http://github.com/gogo/protobuf // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package required import ( "github.com/gogo/protobuf/proto" "github.com/gogo/protobuf/test" "math/rand" "reflect" "strconv" "testing" "time" ) func TestMarshalToErrorsWhenRequiredFieldIsNotPresent(t *testing.T) { data := RequiredExample{} buf, err := proto.Marshal(&data) if err == nil { t.Fatalf("err == nil; was %v instead", err) } if err.Error() != `proto: required field "theRequiredString" not set` { t.Fatalf(`err.Error() != "proto: required field "theRequiredString" not set"; was "%s" instead`, err.Error()) } if len(buf) != 0 { t.Fatalf(`len(buf) != 0; was %d instead`, len(buf)) } } func TestMarshalToSucceedsWhenRequiredFieldIsPresent(t *testing.T) { data := RequiredExample{ TheRequiredString: proto.String("present"), } buf, err := proto.Marshal(&data) if err != nil { t.Fatalf("err != nil; was %v instead", err) } if len(buf) == 0 { t.Fatalf(`len(buf) == 0; expected nonzero`) } } func TestUnmarshalErrorsWhenRequiredFieldIsNotPresent(t *testing.T) { missingRequiredField := []byte{0x12, 0x8, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c} data := RequiredExample{} err := proto.Unmarshal(missingRequiredField, &data) if err == nil { t.Fatalf("err == nil; was %v instead", err) } if err.Error() != `proto: required field "theRequiredString" not set` { t.Fatalf(`err.Error() != "proto: required field "theRequiredString" not set"; was "%s" instead`, err.Error()) } } func TestUnmarshalSucceedsWhenRequiredIsNotPresent(t *testing.T) { dataOut := RequiredExample{ TheRequiredString: proto.String("present"), } encodedMessage, err := proto.Marshal(&dataOut) if err != nil { t.Fatalf("Unexpected error when marshalling dataOut: %v", err) } dataIn := RequiredExample{} err = proto.Unmarshal(encodedMessage, &dataIn) if err != nil { t.Fatalf("err != nil; was %v instead", err) } } func TestUnmarshalPopulatedOptionalFieldsAsRequiredSucceeds(t *testing.T) { r := rand.New(rand.NewSource(time.Now().UnixNano())) dataOut := test.NewPopulatedNidOptNative(r, true) encodedMessage, err := proto.Marshal(dataOut) if err != nil { t.Fatalf("Unexpected error when marshalling dataOut: %v", err) } dataIn := NidOptNative{} err = proto.Unmarshal(encodedMessage, &dataIn) if err != nil { t.Fatalf("err != nil; was %v instead", err) } } func TestUnmarshalPartiallyPopulatedOptionalFieldsFails(t *testing.T) { // Fill in all fields, then randomly remove one. dataOut := &test.NinOptNative{ Field1: proto.Float64(0), Field2: proto.Float32(0), Field3: proto.Int32(0), Field4: proto.Int64(0), Field5: proto.Uint32(0), Field6: proto.Uint64(0), Field7: proto.Int32(0), Field8: proto.Int64(0), Field9: proto.Uint32(0), Field10: proto.Int32(0), Field11: proto.Uint64(0), Field12: proto.Int64(0), Field13: proto.Bool(false), Field14: proto.String("0"), Field15: []byte("0"), } r := rand.New(rand.NewSource(time.Now().UnixNano())) fieldName := "Field" + strconv.Itoa(r.Intn(15)+1) field := reflect.ValueOf(dataOut).Elem().FieldByName(fieldName) fieldType := field.Type() field.Set(reflect.Zero(fieldType)) encodedMessage, err := proto.Marshal(dataOut) if err != nil { t.Fatalf("Unexpected error when marshalling dataOut: %v", err) } dataIn := NidOptNative{} err = proto.Unmarshal(encodedMessage, &dataIn) if err.Error() != `proto: required field "`+fieldName+`" not set` { t.Fatalf(`err.Error() != "proto: required field "`+fieldName+`" not set"; was "%s" instead`, err.Error()) } } func TestMarshalFailsWithoutAllFieldsSet(t *testing.T) { r := rand.New(rand.NewSource(time.Now().UnixNano())) dataOut := NewPopulatedNinOptNative(r, true) fieldName := "Field" + strconv.Itoa(r.Intn(15)+1) field := reflect.ValueOf(dataOut).Elem().FieldByName(fieldName) fieldType := field.Type() field.Set(reflect.Zero(fieldType)) encodedMessage, err := proto.Marshal(dataOut) if err.Error() != `proto: required field "`+fieldName+`" not set` { t.Fatalf(`err.Error() != "proto: required field "`+fieldName+`" not set"; was "%s" instead`, err.Error()) } if len(encodedMessage) > 0 { t.Fatalf("Got some bytes from marshal, expected none.") } } func TestMissingFieldsOnRepeatedNestedTypes(t *testing.T) { r := rand.New(rand.NewSource(time.Now().UnixNano())) dataOut := &NestedNinOptNative{ NestedNinOpts: []*NinOptNative{ NewPopulatedNinOptNative(r, true), NewPopulatedNinOptNative(r, true), NewPopulatedNinOptNative(r, true), }, } middle := dataOut.GetNestedNinOpts()[1] fieldName := "Field" + strconv.Itoa(r.Intn(15)+1) field := reflect.ValueOf(middle).Elem().FieldByName(fieldName) fieldType := field.Type() field.Set(reflect.Zero(fieldType)) encodedMessage, err := proto.Marshal(dataOut) if err.Error() != `proto: required field "`+fieldName+`" not set` { t.Fatalf(`err.Error() != "proto: required field "`+fieldName+`" not set"; was "%s" instead`, err.Error()) } if len(encodedMessage) > 0 { t.Fatalf("Got some bytes from marshal, expected none.") } }