xref: /aosp_15_r20/build/soong/ui/build/paths/logs_test.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1// Copyright 2018 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package paths
16
17import (
18	"context"
19	"io/ioutil"
20	"os"
21	"path/filepath"
22	"reflect"
23	"runtime"
24	"strings"
25	"testing"
26)
27
28func TestSendLog(t *testing.T) {
29	if testing.Short() {
30		t.Skip("skipping in short mode, sometimes hangs")
31	}
32	t.Run("Short name", func(t *testing.T) {
33		d, err := ioutil.TempDir("", "s")
34		if err != nil {
35			t.Fatal(err)
36		}
37		defer os.RemoveAll(d)
38		f := filepath.Join(d, "s")
39
40		testSendLog(t, f, getSocketAddr)
41	})
42
43	testLongName := func(t *testing.T, lookup socketAddrFunc) {
44		d, err := ioutil.TempDir("", strings.Repeat("s", 150))
45		if err != nil {
46			t.Fatal(err)
47		}
48		defer os.RemoveAll(d)
49		f := filepath.Join(d, strings.Repeat("s", 10))
50
51		testSendLog(t, f, lookup)
52	}
53
54	// Using a name longer than the ~100 limit of the underlying calls to bind, etc
55	t.Run("Long name", func(t *testing.T) {
56		testLongName(t, getSocketAddr)
57	})
58
59	if runtime.GOOS == "linux" {
60		t.Run("Long name proc fallback", func(t *testing.T) {
61			testLongName(t, procFallback)
62		})
63	}
64
65	t.Run("Long name tmp fallback", func(t *testing.T) {
66		testLongName(t, tmpFallback)
67	})
68}
69
70func testSendLog(t *testing.T, socket string, lookup socketAddrFunc) {
71	recv, err := logListener(context.Background(), socket, lookup)
72	if err != nil {
73		t.Fatal(err)
74	}
75
76	go func() {
77		for i := 0; i < 10; i++ {
78			sendLog(socket, lookup, 0, &LogEntry{
79				Basename: "test",
80				Args:     []string{"foo", "bar"},
81			}, make(chan interface{}))
82		}
83	}()
84
85	count := 0
86	for {
87		entry := <-recv
88		if entry == nil {
89			if count != 10 {
90				t.Errorf("Expected 10 logs, got %d", count)
91			}
92			return
93		}
94
95		ref := LogEntry{
96			Basename: "test",
97			Args:     []string{"foo", "bar"},
98		}
99		if !reflect.DeepEqual(ref, *entry) {
100			t.Fatalf("Bad log entry: %v", entry)
101		}
102		count++
103
104		if count == 10 {
105			return
106		}
107	}
108}
109
110func TestSendLogError(t *testing.T) {
111	d, err := ioutil.TempDir("", "log_socket")
112	if err != nil {
113		t.Fatal(err)
114	}
115	defer os.RemoveAll(d)
116
117	// Missing log sockets should not block waiting for the timeout to elapse
118	t.Run("Missing file", func(t *testing.T) {
119		sendLog(filepath.Join(d, "missing"), getSocketAddr, 0, &LogEntry{}, make(chan interface{}))
120	})
121
122	// Non-sockets should not block waiting for the timeout to elapse
123	t.Run("Regular file", func(t *testing.T) {
124		f := filepath.Join(d, "file")
125		if fp, err := os.Create(f); err == nil {
126			fp.Close()
127		} else {
128			t.Fatal(err)
129		}
130
131		sendLog(f, getSocketAddr, 0, &LogEntry{}, make(chan interface{}))
132	})
133
134	// If the reader is stuck, we should be able to make progress
135	t.Run("Reader not reading", func(t *testing.T) {
136		f := filepath.Join(d, "sock1")
137
138		ln, err := listen(f, getSocketAddr)
139		if err != nil {
140			t.Fatal(err)
141		}
142		defer ln.Close()
143
144		done := make(chan bool, 1)
145		go func() {
146			for i := 0; i < 10; i++ {
147				sendLog(f, getSocketAddr, timeoutDuration, &LogEntry{
148					// Ensure a relatively large payload
149					Basename: strings.Repeat(" ", 100000),
150				}, make(chan interface{}))
151			}
152			done <- true
153		}()
154
155		<-done
156	})
157}
158