Skip to content

Commit 61f2a44

Browse files
committed
types.Make{Int,String}: Variadic validator functions
The MakeString function got another variadic parameter, allowing multiple validators against the newly created String. As one example, the newly introduced StringMustNotBeEmpty function can be used, mimicking Icinga Notifications' ToDBString behavior. To replace Icinga Notifications' ToDBInt utility function, a similar MakeInt function and IntMustNotBeZero was introduced. Inspired by: - ToDBInt, Icinga/icinga-notifications@f0b39f0 - ToDBString, Icinga/icinga-notifications@8183344
1 parent e543ee2 commit 61f2a44

File tree

4 files changed

+122
-11
lines changed

4 files changed

+122
-11
lines changed

types/int.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,29 @@ type Int struct {
1414
sql.NullInt64
1515
}
1616

17+
// IntMustNotBeZero validates that an Int is valid and not the numerical value zero.
18+
func IntMustNotBeZero(i Int) bool {
19+
return i.Valid && i.Int64 != 0
20+
}
21+
22+
// MakeInt constructs a new Int.
23+
//
24+
// Multiple validators functions can be given, each validating the generated Int. If any returns false, a NULL
25+
// String is returned instead. For example, there is IntMustNotBeZero.
26+
func MakeInt(in int64, validators ...func(Int) bool) Int {
27+
i := Int{sql.NullInt64{
28+
Int64: in,
29+
Valid: true,
30+
}}
31+
32+
for _, validator := range validators {
33+
if !validator(i) {
34+
return Int{sql.NullInt64{Valid: false}}
35+
}
36+
}
37+
return i
38+
}
39+
1740
// MarshalJSON implements the json.Marshaler interface.
1841
// Supports JSON null.
1942
func (i Int) MarshalJSON() ([]byte, error) {

types/int_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,49 @@ import (
66
"testing"
77
)
88

9+
func TestMakeInt(t *testing.T) {
10+
subtests := []struct {
11+
name string
12+
input int64
13+
validators []func(Int) bool
14+
output sql.NullInt64
15+
}{
16+
{
17+
name: "zero",
18+
input: 0,
19+
output: sql.NullInt64{Int64: 0, Valid: true},
20+
},
21+
{
22+
name: "positive",
23+
input: 1,
24+
output: sql.NullInt64{Int64: 1, Valid: true},
25+
},
26+
{
27+
name: "negative",
28+
input: -1,
29+
output: sql.NullInt64{Int64: -1, Valid: true},
30+
},
31+
{
32+
name: "zero-validator-not-zero",
33+
input: 0,
34+
validators: []func(Int) bool{IntMustNotBeZero},
35+
output: sql.NullInt64{Valid: false},
36+
},
37+
{
38+
name: "positive-validator-not-zero",
39+
input: 1,
40+
validators: []func(Int) bool{IntMustNotBeZero},
41+
output: sql.NullInt64{Int64: 1, Valid: true},
42+
},
43+
}
44+
45+
for _, st := range subtests {
46+
t.Run(st.name, func(t *testing.T) {
47+
require.Equal(t, Int{NullInt64: st.output}, MakeInt(st.input, st.validators...))
48+
})
49+
}
50+
}
51+
952
func TestInt_MarshalJSON(t *testing.T) {
1053
subtests := []struct {
1154
name string

types/string.go

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,27 @@ type String struct {
1414
sql.NullString
1515
}
1616

17-
// MakeString constructs a new non-NULL String from s.
18-
func MakeString(s string) String {
19-
return String{sql.NullString{
20-
String: s,
17+
// StringMustNotBeEmpty validates that a String is valid and not empty.
18+
func StringMustNotBeEmpty(s String) bool {
19+
return s.Valid && s.String != ""
20+
}
21+
22+
// MakeString constructs a new String.
23+
//
24+
// Multiple validators functions can be given, each validating the generated String. If any returns false, a NULL
25+
// String is returned instead. For example, there is StringMustNotBeEmpty.
26+
func MakeString(in string, validators ...func(String) bool) String {
27+
s := String{sql.NullString{
28+
String: in,
2129
Valid: true,
2230
}}
31+
32+
for _, validator := range validators {
33+
if !validator(s) {
34+
return String{sql.NullString{Valid: false}}
35+
}
36+
}
37+
return s
2338
}
2439

2540
// MarshalJSON implements the json.Marshaler interface.

types/string_test.go

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,48 @@ import (
99

1010
func TestMakeString(t *testing.T) {
1111
subtests := []struct {
12-
name string
13-
io string
12+
name string
13+
input string
14+
validators []func(String) bool
15+
output sql.NullString
1416
}{
15-
{"empty", ""},
16-
{"nul", "\x00"},
17-
{"space", " "},
18-
{"multiple", "abc"},
17+
{
18+
name: "empty",
19+
input: "",
20+
output: sql.NullString{String: "", Valid: true},
21+
},
22+
{
23+
name: "nul",
24+
input: "\x00",
25+
output: sql.NullString{String: "\x00", Valid: true},
26+
},
27+
{
28+
name: "space",
29+
input: " ",
30+
output: sql.NullString{String: " ", Valid: true},
31+
},
32+
{
33+
name: "valid-text",
34+
input: "abc",
35+
output: sql.NullString{String: "abc", Valid: true},
36+
},
37+
{
38+
name: "empty-validator-not-empty",
39+
input: "",
40+
validators: []func(String) bool{StringMustNotBeEmpty},
41+
output: sql.NullString{Valid: false},
42+
},
43+
{
44+
name: "valid-text-validator-not-empty",
45+
input: "abc",
46+
validators: []func(String) bool{StringMustNotBeEmpty},
47+
output: sql.NullString{String: "abc", Valid: true},
48+
},
1949
}
2050

2151
for _, st := range subtests {
2252
t.Run(st.name, func(t *testing.T) {
23-
require.Equal(t, String{NullString: sql.NullString{String: st.io, Valid: true}}, MakeString(st.io))
53+
require.Equal(t, String{NullString: st.output}, MakeString(st.input, st.validators...))
2454
})
2555
}
2656
}

0 commit comments

Comments
 (0)