1// Copyright The OpenTelemetry Authors
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 testing
16
17import (
18	"os"
19	"testing"
20
21	"github.com/stretchr/testify/assert"
22	"github.com/stretchr/testify/require"
23	"github.com/stretchr/testify/suite"
24)
25
26type EnvStoreTestSuite struct {
27	suite.Suite
28}
29
30func (s *EnvStoreTestSuite) Test_add() {
31	envStore := newEnvStore()
32
33	e := Env{
34		Name:   "name",
35		Value:  "value",
36		Exists: true,
37	}
38	envStore.add(e)
39	envStore.add(e)
40
41	s.Assert().Len(envStore.store, 1)
42}
43
44func (s *EnvStoreTestSuite) TestRecord() {
45	testCases := []struct {
46		name             string
47		env              Env
48		expectedEnvStore *envStore
49	}{
50		{
51			name: "record exists env",
52			env: Env{
53				Name:   "name",
54				Value:  "value",
55				Exists: true,
56			},
57			expectedEnvStore: &envStore{store: map[string]Env{
58				"name": {
59					Name:   "name",
60					Value:  "value",
61					Exists: true,
62				},
63			}},
64		},
65		{
66			name: "record exists env, but its value is empty",
67			env: Env{
68				Name:   "name",
69				Value:  "",
70				Exists: true,
71			},
72			expectedEnvStore: &envStore{store: map[string]Env{
73				"name": {
74					Name:   "name",
75					Value:  "",
76					Exists: true,
77				},
78			}},
79		},
80		{
81			name: "record not exists env",
82			env: Env{
83				Name:   "name",
84				Exists: false,
85			},
86			expectedEnvStore: &envStore{store: map[string]Env{
87				"name": {
88					Name:   "name",
89					Exists: false,
90				},
91			}},
92		},
93	}
94
95	for _, tc := range testCases {
96		s.Run(tc.name, func() {
97			if tc.env.Exists {
98				s.Assert().NoError(os.Setenv(tc.env.Name, tc.env.Value))
99			}
100
101			envStore := newEnvStore()
102			envStore.Record(tc.env.Name)
103
104			s.Assert().Equal(tc.expectedEnvStore, envStore)
105
106			if tc.env.Exists {
107				s.Assert().NoError(os.Unsetenv(tc.env.Name))
108			}
109		})
110	}
111}
112
113func (s *EnvStoreTestSuite) TestRestore() {
114	testCases := []struct {
115		name              string
116		env               Env
117		expectedEnvValue  string
118		expectedEnvExists bool
119	}{
120		{
121			name: "exists env",
122			env: Env{
123				Name:   "name",
124				Value:  "value",
125				Exists: true,
126			},
127			expectedEnvValue:  "value",
128			expectedEnvExists: true,
129		},
130		{
131			name: "no exists env",
132			env: Env{
133				Name:   "name",
134				Exists: false,
135			},
136			expectedEnvExists: false,
137		},
138	}
139
140	for _, tc := range testCases {
141		s.Run(tc.name, func() {
142			envStore := newEnvStore()
143			envStore.add(tc.env)
144
145			// Backup
146			backup := newEnvStore()
147			backup.Record(tc.env.Name)
148
149			s.Require().NoError(os.Unsetenv(tc.env.Name))
150
151			s.Assert().NoError(envStore.Restore())
152			v, exists := os.LookupEnv(tc.env.Name)
153			s.Assert().Equal(tc.expectedEnvValue, v)
154			s.Assert().Equal(tc.expectedEnvExists, exists)
155
156			// Restore
157			s.Require().NoError(backup.Restore())
158		})
159	}
160}
161
162func (s *EnvStoreTestSuite) Test_setEnv() {
163	testCases := []struct {
164		name              string
165		key               string
166		value             string
167		expectedEnvStore  *envStore
168		expectedEnvValue  string
169		expectedEnvExists bool
170	}{
171		{
172			name:  "normal",
173			key:   "name",
174			value: "value",
175			expectedEnvStore: &envStore{store: map[string]Env{
176				"name": {
177					Name:   "name",
178					Value:  "other value",
179					Exists: true,
180				},
181			}},
182			expectedEnvValue:  "value",
183			expectedEnvExists: true,
184		},
185	}
186
187	for _, tc := range testCases {
188		s.Run(tc.name, func() {
189			envStore := newEnvStore()
190
191			// Backup
192			backup := newEnvStore()
193			backup.Record(tc.key)
194
195			s.Require().NoError(os.Setenv(tc.key, "other value"))
196
197			s.Assert().NoError(envStore.setEnv(tc.key, tc.value))
198			s.Assert().Equal(tc.expectedEnvStore, envStore)
199			v, exists := os.LookupEnv(tc.key)
200			s.Assert().Equal(tc.expectedEnvValue, v)
201			s.Assert().Equal(tc.expectedEnvExists, exists)
202
203			// Restore
204			s.Require().NoError(backup.Restore())
205		})
206	}
207}
208
209func TestEnvStoreTestSuite(t *testing.T) {
210	suite.Run(t, new(EnvStoreTestSuite))
211}
212
213func TestSetEnvVariables(t *testing.T) {
214	envs := map[string]string{
215		"name1": "value1",
216		"name2": "value2",
217	}
218
219	// Backup
220	backup := newEnvStore()
221	for k := range envs {
222		backup.Record(k)
223	}
224	defer func() {
225		require.NoError(t, backup.Restore())
226	}()
227
228	store, err := SetEnvVariables(envs)
229	assert.NoError(t, err)
230	require.IsType(t, &envStore{}, store)
231	concreteStore := store.(*envStore)
232	assert.Len(t, concreteStore.store, 2)
233	assert.Equal(t, backup, concreteStore)
234}
235