1// Copyright 2020 Google LLC
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//     https://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
14package wire
15
16import (
17	"fmt"
18	"testing"
19	"time"
20)
21
22func testReceiveSettings() ReceiveSettings {
23	settings := DefaultReceiveSettings
24	settings.Timeout = 5 * time.Second
25	return settings
26}
27
28const serviceTestWaitTimeout = 30 * time.Second
29
30// serviceTestProxy wraps a `service` and provides some convenience methods for
31// testing.
32type serviceTestProxy struct {
33	t          *testing.T
34	service    service
35	name       string
36	clients    apiClients
37	started    chan struct{}
38	terminated chan struct{}
39}
40
41func (sp *serviceTestProxy) initAndStart(t *testing.T, s service, name string, clients ...apiClient) {
42	sp.t = t
43	sp.service = s
44	sp.name = name
45	sp.clients = clients
46	sp.started = make(chan struct{})
47	sp.terminated = make(chan struct{})
48	s.AddStatusChangeReceiver(nil, sp.onStatusChange)
49	s.Start()
50}
51
52func (sp *serviceTestProxy) onStatusChange(_ serviceHandle, status serviceStatus, _ error) {
53	if status == serviceActive {
54		close(sp.started)
55	}
56	if status == serviceTerminated {
57		close(sp.terminated)
58	}
59}
60
61func (sp *serviceTestProxy) Start() { sp.service.Start() }
62func (sp *serviceTestProxy) Stop()  { sp.service.Stop() }
63
64// StartError waits for the service to start and returns the error.
65func (sp *serviceTestProxy) StartError() error {
66	select {
67	case <-time.After(serviceTestWaitTimeout):
68		return fmt.Errorf("%s did not start within %v", sp.name, serviceTestWaitTimeout)
69	case <-sp.terminated:
70		sp.clients.Close()
71		return sp.service.Error()
72	case <-sp.started:
73		return sp.service.Error()
74	}
75}
76
77// FinalError waits for the service to terminate and returns the error.
78func (sp *serviceTestProxy) FinalError() error {
79	select {
80	case <-time.After(serviceTestWaitTimeout):
81		return fmt.Errorf("%s did not terminate within %v", sp.name, serviceTestWaitTimeout)
82	case <-sp.terminated:
83		sp.clients.Close()
84		return sp.service.Error()
85	}
86}
87
88// StopVerifyNoError stops the service, waits for it to terminate and verifies
89// that there is no error.
90func (sp *serviceTestProxy) StopVerifyNoError() {
91	sp.service.Stop()
92	if gotErr := sp.FinalError(); gotErr != nil {
93		sp.t.Errorf("%s final err: (%v), want: <nil>", sp.name, gotErr)
94	}
95}
96