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
29package io_test
30
31import (
32	"bytes"
33	"encoding/binary"
34	"github.com/gogo/protobuf/io"
35	"github.com/gogo/protobuf/test"
36	goio "io"
37	"math/rand"
38	"testing"
39	"time"
40)
41
42func iotest(writer io.WriteCloser, reader io.ReadCloser) error {
43	size := 1000
44	msgs := make([]*test.NinOptNative, size)
45	r := rand.New(rand.NewSource(time.Now().UnixNano()))
46	for i := range msgs {
47		msgs[i] = test.NewPopulatedNinOptNative(r, true)
48		//issue 31
49		if i == 5 {
50			msgs[i] = &test.NinOptNative{}
51		}
52		//issue 31
53		if i == 999 {
54			msgs[i] = &test.NinOptNative{}
55		}
56		err := writer.WriteMsg(msgs[i])
57		if err != nil {
58			return err
59		}
60	}
61	if err := writer.Close(); err != nil {
62		return err
63	}
64	i := 0
65	for {
66		msg := &test.NinOptNative{}
67		if err := reader.ReadMsg(msg); err != nil {
68			if err == goio.EOF {
69				break
70			}
71			return err
72		}
73		if err := msg.VerboseEqual(msgs[i]); err != nil {
74			return err
75		}
76		i++
77	}
78	if i != size {
79		panic("not enough messages read")
80	}
81	if err := reader.Close(); err != nil {
82		return err
83	}
84	return nil
85}
86
87type buffer struct {
88	*bytes.Buffer
89	closed bool
90}
91
92func (this *buffer) Close() error {
93	this.closed = true
94	return nil
95}
96
97func newBuffer() *buffer {
98	return &buffer{bytes.NewBuffer(nil), false}
99}
100
101func TestBigUint32Normal(t *testing.T) {
102	buf := newBuffer()
103	writer := io.NewUint32DelimitedWriter(buf, binary.BigEndian)
104	reader := io.NewUint32DelimitedReader(buf, binary.BigEndian, 1024*1024)
105	if err := iotest(writer, reader); err != nil {
106		t.Error(err)
107	}
108	if !buf.closed {
109		t.Fatalf("did not close buffer")
110	}
111}
112
113func TestBigUint32MaxSize(t *testing.T) {
114	buf := newBuffer()
115	writer := io.NewUint32DelimitedWriter(buf, binary.BigEndian)
116	reader := io.NewUint32DelimitedReader(buf, binary.BigEndian, 20)
117	if err := iotest(writer, reader); err != goio.ErrShortBuffer {
118		t.Error(err)
119	} else {
120		t.Logf("%s", err)
121	}
122}
123
124func TestLittleUint32Normal(t *testing.T) {
125	buf := newBuffer()
126	writer := io.NewUint32DelimitedWriter(buf, binary.LittleEndian)
127	reader := io.NewUint32DelimitedReader(buf, binary.LittleEndian, 1024*1024)
128	if err := iotest(writer, reader); err != nil {
129		t.Error(err)
130	}
131	if !buf.closed {
132		t.Fatalf("did not close buffer")
133	}
134}
135
136func TestLittleUint32MaxSize(t *testing.T) {
137	buf := newBuffer()
138	writer := io.NewUint32DelimitedWriter(buf, binary.LittleEndian)
139	reader := io.NewUint32DelimitedReader(buf, binary.LittleEndian, 20)
140	if err := iotest(writer, reader); err != goio.ErrShortBuffer {
141		t.Error(err)
142	} else {
143		t.Logf("%s", err)
144	}
145}
146
147func TestVarintNormal(t *testing.T) {
148	buf := newBuffer()
149	writer := io.NewDelimitedWriter(buf)
150	reader := io.NewDelimitedReader(buf, 1024*1024)
151	if err := iotest(writer, reader); err != nil {
152		t.Error(err)
153	}
154	if !buf.closed {
155		t.Fatalf("did not close buffer")
156	}
157}
158
159func TestVarintNoClose(t *testing.T) {
160	buf := bytes.NewBuffer(nil)
161	writer := io.NewDelimitedWriter(buf)
162	reader := io.NewDelimitedReader(buf, 1024*1024)
163	if err := iotest(writer, reader); err != nil {
164		t.Error(err)
165	}
166}
167
168//issue 32
169func TestVarintMaxSize(t *testing.T) {
170	buf := newBuffer()
171	writer := io.NewDelimitedWriter(buf)
172	reader := io.NewDelimitedReader(buf, 20)
173	if err := iotest(writer, reader); err != goio.ErrShortBuffer {
174		t.Error(err)
175	} else {
176		t.Logf("%s", err)
177	}
178}
179
180func TestVarintError(t *testing.T) {
181	buf := newBuffer()
182	buf.Write([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f})
183	reader := io.NewDelimitedReader(buf, 1024*1024)
184	msg := &test.NinOptNative{}
185	err := reader.ReadMsg(msg)
186	if err == nil {
187		t.Fatalf("Expected error")
188	}
189}
190
191func TestFull(t *testing.T) {
192	buf := newBuffer()
193	writer := io.NewFullWriter(buf)
194	reader := io.NewFullReader(buf, 1024*1024)
195	r := rand.New(rand.NewSource(time.Now().UnixNano()))
196	msgIn := test.NewPopulatedNinOptNative(r, true)
197	if err := writer.WriteMsg(msgIn); err != nil {
198		panic(err)
199	}
200	if err := writer.Close(); err != nil {
201		panic(err)
202	}
203	msgOut := &test.NinOptNative{}
204	if err := reader.ReadMsg(msgOut); err != nil {
205		panic(err)
206	}
207	if err := msgIn.VerboseEqual(msgOut); err != nil {
208		panic(err)
209	}
210	if err := reader.ReadMsg(msgOut); err != nil {
211		if err != goio.EOF {
212			panic(err)
213		}
214	}
215	if err := reader.Close(); err != nil {
216		panic(err)
217	}
218	if !buf.closed {
219		t.Fatalf("did not close buffer")
220	}
221}
222