@@ -3,11 +3,14 @@ package logger
3
3
import (
4
4
"bytes"
5
5
"fmt"
6
+ "io"
7
+ "os"
6
8
"strings"
7
9
"testing"
8
10
9
11
tftesting "github.com/gruntwork-io/terratest/modules/testing"
10
12
"github.com/stretchr/testify/assert"
13
+ "github.com/stretchr/testify/require"
11
14
)
12
15
13
16
func TestDoLog (t * testing.T ) {
@@ -52,3 +55,54 @@ func TestCustomLogger(t *testing.T) {
52
55
assert .Equal (t , "log output 2" , c .logs [1 ])
53
56
assert .Equal (t , "subtest log" , c .logs [2 ])
54
57
}
58
+
59
+ // TestLockedLog make sure that Log and Logf which use stdout are thread-safe
60
+ func TestLockedLog (t * testing.T ) {
61
+ // should not call t.Parallel() since we are modifying os.Stdout
62
+ stdout := os .Stdout
63
+ t .Cleanup (func () {
64
+ os .Stdout = stdout
65
+ })
66
+
67
+ data := []struct {
68
+ name string
69
+ fn func (* testing.T , string )
70
+ }{
71
+ {
72
+ name : "Log" ,
73
+ fn : func (t * testing.T , s string ) {
74
+ Log (t , s )
75
+ }},
76
+ {
77
+ name : "Logf" ,
78
+ fn : func (t * testing.T , s string ) {
79
+ Logf (t , "%s" , s )
80
+ }},
81
+ }
82
+
83
+ for _ , d := range data {
84
+ mutexStdout .Lock ()
85
+ str := "Logging something" + t .Name ()
86
+
87
+ r , w , _ := os .Pipe ()
88
+ os .Stdout = w
89
+ ch := make (chan struct {})
90
+ go func () {
91
+ d .fn (t , str )
92
+ w .Close ()
93
+ close (ch )
94
+ }()
95
+
96
+ select {
97
+ case <- ch :
98
+ t .Error ("Log should be locked" )
99
+ default :
100
+ }
101
+
102
+ mutexStdout .Unlock ()
103
+ b , err := io .ReadAll (r )
104
+ require .NoError (t , err , "log should be unlocked" )
105
+ assert .Contains (t , string (b ), str , "should contains logged string" )
106
+ }
107
+
108
+ }
0 commit comments