1// Copyright 2022 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package saferio
6
7import (
8	"bytes"
9	"io"
10	"testing"
11)
12
13func TestReadData(t *testing.T) {
14	const count = 100
15	input := bytes.Repeat([]byte{'a'}, count)
16
17	t.Run("small", func(t *testing.T) {
18		got, err := ReadData(bytes.NewReader(input), count)
19		if err != nil {
20			t.Fatal(err)
21		}
22		if !bytes.Equal(got, input) {
23			t.Errorf("got %v, want %v", got, input)
24		}
25	})
26
27	t.Run("large", func(t *testing.T) {
28		_, err := ReadData(bytes.NewReader(input), 10<<30)
29		if err == nil {
30			t.Error("large read succeeded unexpectedly")
31		}
32	})
33
34	t.Run("maxint", func(t *testing.T) {
35		_, err := ReadData(bytes.NewReader(input), 1<<62)
36		if err == nil {
37			t.Error("large read succeeded unexpectedly")
38		}
39	})
40
41	t.Run("small-EOF", func(t *testing.T) {
42		_, err := ReadData(bytes.NewReader(nil), chunk-1)
43		if err != io.EOF {
44			t.Errorf("ReadData = %v, want io.EOF", err)
45		}
46	})
47
48	t.Run("large-EOF", func(t *testing.T) {
49		_, err := ReadData(bytes.NewReader(nil), chunk+1)
50		if err != io.EOF {
51			t.Errorf("ReadData = %v, want io.EOF", err)
52		}
53	})
54
55	t.Run("large-UnexpectedEOF", func(t *testing.T) {
56		_, err := ReadData(bytes.NewReader(make([]byte, chunk)), chunk+1)
57		if err != io.ErrUnexpectedEOF {
58			t.Errorf("ReadData = %v, want io.ErrUnexpectedEOF", err)
59		}
60	})
61}
62
63func TestReadDataAt(t *testing.T) {
64	const count = 100
65	input := bytes.Repeat([]byte{'a'}, count)
66
67	t.Run("small", func(t *testing.T) {
68		got, err := ReadDataAt(bytes.NewReader(input), count, 0)
69		if err != nil {
70			t.Fatal(err)
71		}
72		if !bytes.Equal(got, input) {
73			t.Errorf("got %v, want %v", got, input)
74		}
75	})
76
77	t.Run("large", func(t *testing.T) {
78		_, err := ReadDataAt(bytes.NewReader(input), 10<<30, 0)
79		if err == nil {
80			t.Error("large read succeeded unexpectedly")
81		}
82	})
83
84	t.Run("maxint", func(t *testing.T) {
85		_, err := ReadDataAt(bytes.NewReader(input), 1<<62, 0)
86		if err == nil {
87			t.Error("large read succeeded unexpectedly")
88		}
89	})
90
91	t.Run("SectionReader", func(t *testing.T) {
92		// Reading 0 bytes from an io.SectionReader at the end
93		// of the section will return EOF, but ReadDataAt
94		// should succeed and return 0 bytes.
95		sr := io.NewSectionReader(bytes.NewReader(input), 0, 0)
96		got, err := ReadDataAt(sr, 0, 0)
97		if err != nil {
98			t.Fatal(err)
99		}
100		if len(got) > 0 {
101			t.Errorf("got %d bytes, expected 0", len(got))
102		}
103	})
104}
105
106func TestSliceCap(t *testing.T) {
107	t.Run("small", func(t *testing.T) {
108		c := SliceCap[int](10)
109		if c != 10 {
110			t.Errorf("got capacity %d, want %d", c, 10)
111		}
112	})
113
114	t.Run("large", func(t *testing.T) {
115		c := SliceCap[byte](1 << 30)
116		if c < 0 {
117			t.Error("SliceCap failed unexpectedly")
118		} else if c == 1<<30 {
119			t.Errorf("got capacity %d which is too high", c)
120		}
121	})
122
123	t.Run("maxint", func(t *testing.T) {
124		c := SliceCap[byte](1 << 63)
125		if c >= 0 {
126			t.Errorf("SliceCap returned %d, expected failure", c)
127		}
128	})
129
130	t.Run("overflow", func(t *testing.T) {
131		c := SliceCap[int64](1 << 62)
132		if c >= 0 {
133			t.Errorf("SliceCap returned %d, expected failure", c)
134		}
135	})
136}
137