mirror of https://github.com/grafana/grafana
Settings: Fix data race when dynamically overriding settings with environment variables (#81667)
Chore: Fix data race when dynamically overriding settings with environment variablespull/81897/head
parent
c87e4eb724
commit
b02f0b926a
@ -0,0 +1,42 @@ |
|||||||
|
package osutil |
||||||
|
|
||||||
|
import ( |
||||||
|
"os" |
||||||
|
) |
||||||
|
|
||||||
|
// Env collects global functions from standard package "os" that are related to
|
||||||
|
// environment variables. This allows abstracting code and provides a way to
|
||||||
|
// concurrently test code that needs access to these shared resources.
|
||||||
|
type Env interface { |
||||||
|
Setenv(key, value string) error |
||||||
|
Getenv(key string) string |
||||||
|
} |
||||||
|
|
||||||
|
// RealEnv implements Env interface by calling the actual global functions in
|
||||||
|
// package "os". This should be used by default anywhere that an Env is
|
||||||
|
// expected, and use MapEnv instead in your unit tests.
|
||||||
|
type RealEnv struct{} |
||||||
|
|
||||||
|
func (RealEnv) Setenv(key, value string) error { |
||||||
|
return os.Setenv(key, value) |
||||||
|
} |
||||||
|
|
||||||
|
func (RealEnv) Getenv(key string) string { |
||||||
|
return os.Getenv(key) |
||||||
|
} |
||||||
|
|
||||||
|
// MapEnv is a fake implementing Env interface. It is purposefully not
|
||||||
|
// concurrency-safe, so if your tests using it panic due to concurrent map
|
||||||
|
// access, then you need to fix a data race in your code. This is
|
||||||
|
// because environment variables are globals to a process, so you should be
|
||||||
|
// properly synchronizing access to them (e.g. with a mutex).
|
||||||
|
type MapEnv map[string]string |
||||||
|
|
||||||
|
func (m MapEnv) Setenv(key, value string) error { |
||||||
|
m[key] = value |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
func (m MapEnv) Getenv(key string) string { |
||||||
|
return m[key] |
||||||
|
} |
@ -0,0 +1,35 @@ |
|||||||
|
package osutil |
||||||
|
|
||||||
|
import ( |
||||||
|
"os" |
||||||
|
"testing" |
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert" |
||||||
|
) |
||||||
|
|
||||||
|
func TestRealEnv(t *testing.T) { |
||||||
|
// testing here is obviously not parallel since we do need to access real
|
||||||
|
// environment variables from the os
|
||||||
|
|
||||||
|
const key = "MEREKETENGUE" |
||||||
|
const value = "IS ALIVE" |
||||||
|
|
||||||
|
assert.Equal(t, os.Getenv(key), RealEnv{}.Getenv(key)) |
||||||
|
assert.NoError(t, RealEnv{}.Setenv(key, value)) |
||||||
|
assert.Equal(t, value, RealEnv{}.Getenv(key)) |
||||||
|
assert.Equal(t, value, os.Getenv(key)) |
||||||
|
} |
||||||
|
|
||||||
|
func TestMapEnv(t *testing.T) { |
||||||
|
t.Parallel() |
||||||
|
|
||||||
|
const key = "THE_THING" |
||||||
|
const value = "IS ALIVE" |
||||||
|
|
||||||
|
e := MapEnv{} |
||||||
|
assert.Empty(t, e.Getenv(key)) |
||||||
|
assert.Len(t, e, 0) |
||||||
|
assert.NoError(t, e.Setenv(key, value)) |
||||||
|
assert.Equal(t, value, e.Getenv(key)) |
||||||
|
assert.Len(t, e, 1) |
||||||
|
} |
Loading…
Reference in new issue