1// Copyright 2019 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 iotest
6
7import (
8	"bytes"
9	"errors"
10	"fmt"
11	"log"
12	"strings"
13	"testing"
14)
15
16type errWriter struct {
17	err error
18}
19
20func (w errWriter) Write([]byte) (int, error) {
21	return 0, w.err
22}
23
24func TestWriteLogger(t *testing.T) {
25	olw := log.Writer()
26	olf := log.Flags()
27	olp := log.Prefix()
28
29	// Revert the original log settings before we exit.
30	defer func() {
31		log.SetFlags(olf)
32		log.SetPrefix(olp)
33		log.SetOutput(olw)
34	}()
35
36	lOut := new(strings.Builder)
37	log.SetPrefix("lw: ")
38	log.SetOutput(lOut)
39	log.SetFlags(0)
40
41	lw := new(strings.Builder)
42	wl := NewWriteLogger("write:", lw)
43	if _, err := wl.Write([]byte("Hello, World!")); err != nil {
44		t.Fatalf("Unexpectedly failed to write: %v", err)
45	}
46
47	if g, w := lw.String(), "Hello, World!"; g != w {
48		t.Errorf("WriteLogger mismatch\n\tgot:  %q\n\twant: %q", g, w)
49	}
50	wantLogWithHex := fmt.Sprintf("lw: write: %x\n", "Hello, World!")
51	if g, w := lOut.String(), wantLogWithHex; g != w {
52		t.Errorf("WriteLogger mismatch\n\tgot:  %q\n\twant: %q", g, w)
53	}
54}
55
56func TestWriteLogger_errorOnWrite(t *testing.T) {
57	olw := log.Writer()
58	olf := log.Flags()
59	olp := log.Prefix()
60
61	// Revert the original log settings before we exit.
62	defer func() {
63		log.SetFlags(olf)
64		log.SetPrefix(olp)
65		log.SetOutput(olw)
66	}()
67
68	lOut := new(strings.Builder)
69	log.SetPrefix("lw: ")
70	log.SetOutput(lOut)
71	log.SetFlags(0)
72
73	lw := errWriter{err: errors.New("Write Error!")}
74	wl := NewWriteLogger("write:", lw)
75	if _, err := wl.Write([]byte("Hello, World!")); err == nil {
76		t.Fatalf("Unexpectedly succeeded to write: %v", err)
77	}
78
79	wantLogWithHex := fmt.Sprintf("lw: write: %x: %v\n", "", "Write Error!")
80	if g, w := lOut.String(), wantLogWithHex; g != w {
81		t.Errorf("WriteLogger mismatch\n\tgot:  %q\n\twant: %q", g, w)
82	}
83}
84
85func TestReadLogger(t *testing.T) {
86	olw := log.Writer()
87	olf := log.Flags()
88	olp := log.Prefix()
89
90	// Revert the original log settings before we exit.
91	defer func() {
92		log.SetFlags(olf)
93		log.SetPrefix(olp)
94		log.SetOutput(olw)
95	}()
96
97	lOut := new(strings.Builder)
98	log.SetPrefix("lr: ")
99	log.SetOutput(lOut)
100	log.SetFlags(0)
101
102	data := []byte("Hello, World!")
103	p := make([]byte, len(data))
104	lr := bytes.NewReader(data)
105	rl := NewReadLogger("read:", lr)
106
107	n, err := rl.Read(p)
108	if err != nil {
109		t.Fatalf("Unexpectedly failed to read: %v", err)
110	}
111
112	if g, w := p[:n], data; !bytes.Equal(g, w) {
113		t.Errorf("ReadLogger mismatch\n\tgot:  %q\n\twant: %q", g, w)
114	}
115
116	wantLogWithHex := fmt.Sprintf("lr: read: %x\n", "Hello, World!")
117	if g, w := lOut.String(), wantLogWithHex; g != w {
118		t.Errorf("ReadLogger mismatch\n\tgot:  %q\n\twant: %q", g, w)
119	}
120}
121
122func TestReadLogger_errorOnRead(t *testing.T) {
123	olw := log.Writer()
124	olf := log.Flags()
125	olp := log.Prefix()
126
127	// Revert the original log settings before we exit.
128	defer func() {
129		log.SetFlags(olf)
130		log.SetPrefix(olp)
131		log.SetOutput(olw)
132	}()
133
134	lOut := new(strings.Builder)
135	log.SetPrefix("lr: ")
136	log.SetOutput(lOut)
137	log.SetFlags(0)
138
139	data := []byte("Hello, World!")
140	p := make([]byte, len(data))
141
142	lr := ErrReader(errors.New("io failure"))
143	rl := NewReadLogger("read", lr)
144	n, err := rl.Read(p)
145	if err == nil {
146		t.Fatalf("Unexpectedly succeeded to read: %v", err)
147	}
148
149	wantLogWithHex := fmt.Sprintf("lr: read %x: io failure\n", p[:n])
150	if g, w := lOut.String(), wantLogWithHex; g != w {
151		t.Errorf("ReadLogger mismatch\n\tgot:  %q\n\twant: %q", g, w)
152	}
153}
154