1package tfe
2
3import (
4	"context"
5	"io/ioutil"
6	"net/http"
7	"net/http/httptest"
8	"net/url"
9	"testing"
10)
11
12func testLogReader(t *testing.T, h http.HandlerFunc) (*httptest.Server, *LogReader) {
13	ts := httptest.NewServer(h)
14
15	cfg := &Config{
16		Address:    ts.URL,
17		Token:      "dummy-token",
18		HTTPClient: ts.Client(),
19	}
20
21	client, err := NewClient(cfg)
22	if err != nil {
23		t.Fatal(err)
24	}
25
26	logURL, err := url.Parse(ts.URL)
27	if err != nil {
28		t.Fatal(err)
29	}
30
31	lr := &LogReader{
32		client: client,
33		ctx:    context.Background(),
34		logURL: logURL,
35	}
36
37	return ts, lr
38}
39
40func TestLogReader_withMarkersSingle(t *testing.T) {
41	t.Parallel()
42
43	logReads := 0
44	ts, lr := testLogReader(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
45		logReads++
46		switch {
47		case logReads == 2:
48			w.Write([]byte("\x02Terraform run started - logs - Terraform run finished\x03"))
49		}
50	}))
51	defer ts.Close()
52
53	doneReads := 0
54	lr.done = func() (bool, error) {
55		doneReads++
56		if logReads >= 2 {
57			return true, nil
58		}
59		return false, nil
60	}
61
62	logs, err := ioutil.ReadAll(lr)
63	if err != nil {
64		t.Fatal(err)
65	}
66
67	expected := "Terraform run started - logs - Terraform run finished"
68	if string(logs) != expected {
69		t.Fatalf("expected %s, got: %s", expected, string(logs))
70	}
71	if doneReads != 1 {
72		t.Fatalf("expected 1 done reads, got %d reads", doneReads)
73	}
74	if logReads != 3 {
75		t.Fatalf("expected 3 log reads, got %d reads", logReads)
76	}
77}
78
79func TestLogReader_withMarkersDouble(t *testing.T) {
80	t.Parallel()
81
82	logReads := 0
83	ts, lr := testLogReader(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
84		logReads++
85		switch {
86		case logReads == 2:
87			w.Write([]byte("\x02Terraform run started"))
88		case logReads == 3:
89			w.Write([]byte(" - logs - Terraform run finished\x03"))
90		}
91	}))
92	defer ts.Close()
93
94	doneReads := 0
95	lr.done = func() (bool, error) {
96		doneReads++
97		if logReads >= 3 {
98			return true, nil
99		}
100		return false, nil
101	}
102
103	logs, err := ioutil.ReadAll(lr)
104	if err != nil {
105		t.Fatal(err)
106	}
107
108	expected := "Terraform run started - logs - Terraform run finished"
109	if string(logs) != expected {
110		t.Fatalf("expected %s, got: %s", expected, string(logs))
111	}
112	if doneReads != 1 {
113		t.Fatalf("expected 1 done reads, got %d reads", doneReads)
114	}
115	if logReads != 4 {
116		t.Fatalf("expected 4 log reads, got %d reads", logReads)
117	}
118}
119
120func TestLogReader_withMarkersMulti(t *testing.T) {
121	t.Parallel()
122
123	logReads := 0
124	ts, lr := testLogReader(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
125		logReads++
126		switch {
127		case logReads == 2:
128			w.Write([]byte("\x02"))
129		case logReads == 3:
130			w.Write([]byte("Terraform run started"))
131		case logReads == 16:
132			w.Write([]byte(" - logs - "))
133		case logReads == 30:
134			w.Write([]byte("Terraform run finished"))
135		case logReads == 31:
136			w.Write([]byte("\x03"))
137		}
138	}))
139	defer ts.Close()
140
141	doneReads := 0
142	lr.done = func() (bool, error) {
143		doneReads++
144		if logReads >= 31 {
145			return true, nil
146		}
147		return false, nil
148	}
149
150	logs, err := ioutil.ReadAll(lr)
151	if err != nil {
152		t.Fatal(err)
153	}
154
155	expected := "Terraform run started - logs - Terraform run finished"
156	if string(logs) != expected {
157		t.Fatalf("expected %s, got: %s", expected, string(logs))
158	}
159	if doneReads != 3 {
160		t.Fatalf("expected 3 done reads, got %d reads", doneReads)
161	}
162	if logReads != 31 {
163		t.Fatalf("expected 31 log reads, got %d reads", logReads)
164	}
165}
166
167func TestLogReader_withoutMarkers(t *testing.T) {
168	t.Parallel()
169
170	logReads := 0
171	ts, lr := testLogReader(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
172		logReads++
173		switch {
174		case logReads == 2:
175			w.Write([]byte("Terraform run started"))
176		case logReads == 16:
177			w.Write([]byte(" - logs - "))
178		case logReads == 31:
179			w.Write([]byte("Terraform run finished"))
180		}
181	}))
182	defer ts.Close()
183
184	doneReads := 0
185	lr.done = func() (bool, error) {
186		doneReads++
187		if logReads >= 31 {
188			return true, nil
189		}
190		return false, nil
191	}
192
193	logs, err := ioutil.ReadAll(lr)
194	if err != nil {
195		t.Fatal(err)
196	}
197
198	expected := "Terraform run started - logs - Terraform run finished"
199	if string(logs) != expected {
200		t.Fatalf("expected %s, got: %s", expected, string(logs))
201	}
202	if doneReads != 25 {
203		t.Fatalf("expected 14 done reads, got %d reads", doneReads)
204	}
205	if logReads != 32 {
206		t.Fatalf("expected 32 log reads, got %d reads", logReads)
207	}
208}
209
210func TestLogReader_withoutEndOfTextMarker(t *testing.T) {
211	t.Parallel()
212
213	logReads := 0
214	ts, lr := testLogReader(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
215		logReads++
216		switch {
217		case logReads == 2:
218			w.Write([]byte("\x02"))
219		case logReads == 3:
220			w.Write([]byte("Terraform run started"))
221		case logReads == 16:
222			w.Write([]byte(" - logs - "))
223		case logReads == 31:
224			w.Write([]byte("Terraform run finished"))
225		}
226	}))
227	defer ts.Close()
228
229	doneReads := 0
230	lr.done = func() (bool, error) {
231		doneReads++
232		if logReads >= 31 {
233			return true, nil
234		}
235		return false, nil
236	}
237
238	logs, err := ioutil.ReadAll(lr)
239	if err != nil {
240		t.Fatal(err)
241	}
242
243	expected := "Terraform run started - logs - Terraform run finished"
244	if string(logs) != expected {
245		t.Fatalf("expected %s, got: %s", expected, string(logs))
246	}
247	if doneReads != 3 {
248		t.Fatalf("expected 3 done reads, got %d reads", doneReads)
249	}
250	if logReads != 42 {
251		t.Fatalf("expected 42 log reads, got %d reads", logReads)
252	}
253}
254