-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
pkg/mock: add a mock of os.Exit for testing purposes
- Loading branch information
tav
committed
Jan 27, 2020
1 parent
b845eaf
commit 915fce2
Showing
2 changed files
with
123 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
// Public Domain (-) 2018-present, The Core Authors. | ||
// See the Core UNLICENSE file for details. | ||
|
||
// Package osexit mocks the os.Exit function. | ||
// | ||
// To use, first set a package-specific osExit function, e.g. | ||
// | ||
// var osExit = os.Exit | ||
// | ||
// Then use that when you want to call os.Exit, e.g. | ||
// | ||
// if somethingFatal { | ||
// osExit(1) | ||
// return | ||
// } | ||
// | ||
// Make sure to return immediately after the call to osExit, so that testing | ||
// code will match real code as closely as possible. | ||
// | ||
// You can now use the utility functions provided by this package to override | ||
// osExit for testing purposes, e.g. | ||
// | ||
// osExit = osexit.Set() | ||
// invokeCodeCallingExit() | ||
// if !osexit.Called() { | ||
// t.Fatalf("os.Exit was not called as expected") | ||
// } | ||
// | ||
package osexit | ||
|
||
import ( | ||
"sync" | ||
) | ||
|
||
var ( | ||
called bool | ||
mu sync.RWMutex // protects called, status | ||
status int | ||
) | ||
|
||
// Called returns whether the mock os.Exit function was called. | ||
func Called() bool { | ||
mu.RLock() | ||
c := called | ||
mu.RUnlock() | ||
return c | ||
} | ||
|
||
// Func provides a mock for the os.Exit function. Special care must be taken | ||
// when testing os.Exit to make sure no code runs after the call to Exit. It's | ||
// recommended to put a return statement after Exit calls so that the behaviour | ||
// of the mock matches that of the real function as much as possible. | ||
func Func(code int) { | ||
mu.Lock() | ||
if called { | ||
mu.Unlock() | ||
return | ||
} | ||
called = true | ||
status = code | ||
mu.Unlock() | ||
} | ||
|
||
// Reset resets the state of the mock function. | ||
func Reset() { | ||
mu.Lock() | ||
called = false | ||
status = 0 | ||
mu.Unlock() | ||
} | ||
|
||
// Set returns the mock os.Exit function after calling Reset. | ||
func Set() func(int) { | ||
Reset() | ||
return Func | ||
} | ||
|
||
// Status returns the status code that the mock os.Exit function was called | ||
// with. | ||
func Status() int { | ||
mu.RLock() | ||
s := status | ||
mu.RUnlock() | ||
return s | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
// Public Domain (-) 2018-present, The Core Authors. | ||
// See the Core UNLICENSE file for details. | ||
|
||
package osexit_test | ||
|
||
import ( | ||
"os" | ||
"testing" | ||
|
||
"espra.com/pkg/mock/osexit" | ||
) | ||
|
||
var osExit = os.Exit | ||
|
||
func TestOsExit(t *testing.T) { | ||
osExit = osexit.Set() | ||
osExit(2) | ||
if !osexit.Called() { | ||
t.Fatalf("mock exit function was not called") | ||
} | ||
status := osexit.Status() | ||
if status != 2 { | ||
t.Fatalf("mock exit function did not set the right status code: got %d, want 2", status) | ||
} | ||
osExit(3) | ||
status = osexit.Status() | ||
if status != 2 { | ||
t.Fatalf("mock exit function overrode the status set by a previous call: got %d, want 2", status) | ||
} | ||
osexit.Reset() | ||
if osexit.Called() { | ||
t.Fatalf("the reset mock exit function claims to have been called") | ||
} | ||
status = osexit.Status() | ||
if status != 0 { | ||
t.Fatalf("the reset mock exit function returned a non-zero status code: got %d, want 0", status) | ||
} | ||
} |