Skip to content

Commit

Permalink
feat(condition): Add Number Equal To Inspector (#187)
Browse files Browse the repository at this point in the history
* feat(condition): Add number equal to inspector

* refactor: update tests, substation files

* refactor: add no lint for gocyclo
  • Loading branch information
Mallika05 authored Jun 21, 2024
1 parent b949014 commit aa1d54e
Show file tree
Hide file tree
Showing 5 changed files with 222 additions and 3 deletions.
11 changes: 9 additions & 2 deletions build/config/substation.libsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,15 @@
num: $.condition.number,
number: {
default: {
object: $.config.object,
value: null,
object: $.config.object,
value: null,
},
eq(settings={}): $.condition.number.equal_to(settings=settings),
equal_to(settings={}): {
local default = $.condition.number.default,

type: 'number_equal_to',
settings: std.prune(std.mergePatch(default, $.helpers.abbv(settings))),
},
lt(settings={}): $.condition.number.less_than(settings=settings),
less_than(settings={}): {
Expand Down
3 changes: 2 additions & 1 deletion build/config/substation_test.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ local inspector = sub.condition.format.json();
{
condition: {
number: {
equal_to: sub.condition.number.equal_to({obj: {src: src}, value: 1}),
less_than: sub.condition.number.less_than({obj: {src: src}, value: 1}),
greater_than: sub.condition.number.greater_than({obj: {src: src}, value: 1}),
}
},
},
transform: {
send: {
Expand Down
2 changes: 2 additions & 0 deletions condition/condition.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ func newInspector(ctx context.Context, cfg config.Config) (inspector, error) { /
case "network_ip_valid":
return newNetworkIPValid(ctx, cfg)
// Number inspectors.
case "number_equal_to":
return newNumberEqualTo(ctx, cfg)
case "number_less_than":
return newNumberLessThan(ctx, cfg)
case "number_greater_than":
Expand Down
51 changes: 51 additions & 0 deletions condition/number_equal_to.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package condition

import (
"context"
"encoding/json"
"strconv"

"github.com/brexhq/substation/config"
"github.com/brexhq/substation/message"
)

func newNumberEqualTo(_ context.Context, cfg config.Config) (*numberEqualTo, error) {
conf := numberConfig{}
if err := conf.Decode(cfg.Settings); err != nil {
return nil, err
}
insp := numberEqualTo{
conf: conf,
}
return &insp, nil
}

type numberEqualTo struct {
conf numberConfig
}

func (insp *numberEqualTo) Inspect(ctx context.Context, msg *message.Message) (output bool, err error) {
if msg.IsControl() {
return false, nil
}

if insp.conf.Object.SourceKey == "" {
f, err := strconv.ParseFloat(string(msg.Data()), 64)
if err != nil {
return false, err
}

return insp.match(f), nil
}
v := msg.GetValue(insp.conf.Object.SourceKey)
return insp.match(v.Float()), nil
}

func (c *numberEqualTo) match(f float64) bool {
return f == c.conf.Value
}

func (c *numberEqualTo) String() string {
b, _ := json.Marshal(c.conf)
return string(b)
}
158 changes: 158 additions & 0 deletions condition/number_equal_to_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
package condition

import (
"context"
"testing"

"github.com/brexhq/substation/config"
"github.com/brexhq/substation/message"
)

var _ inspector = &numberEqualTo{}

var numberEqualToTests = []struct {
name string
cfg config.Config
test []byte
expected bool
}{
// Integers
{
"pass",
config.Config{
Settings: map[string]interface{}{
"object": map[string]interface{}{
"source_key": "foo",
},
"value": 14,
},
},
[]byte(`{"foo":14}`),
true,
},
{
"fail",
config.Config{
Settings: map[string]interface{}{
"value": 10,
},
},
[]byte(`1`),
false,
},
{
"pass",
config.Config{
Settings: map[string]interface{}{
"object": map[string]interface{}{
"source_key": "foo",
},
"value": 0,
},
},
[]byte(`{"foo":0}`),
true,
},
{
"fail",
config.Config{
Settings: map[string]interface{}{
"value": 5,
},
},
[]byte(`15`),
false,
},
// Floats
{
"fail",
config.Config{
Settings: map[string]interface{}{
"value": 1,
},
},
[]byte(`1.5`),
false,
},
{
"fail",
config.Config{
Settings: map[string]interface{}{
"value": 0.1,
},
},
[]byte(`1.5`),
false,
},
{
"pass",
config.Config{
Settings: map[string]interface{}{
"object": map[string]interface{}{
"source_key": "foo",
},
"value": 1.1,
},
},
[]byte(`{"foo":1.1}`),
true,
},
{
"pass",
config.Config{
Settings: map[string]interface{}{
"value": 1.4,
},
},
[]byte(`1.4`),
true,
},
}

func TestNumberEqualTo(t *testing.T) {
ctx := context.TODO()

for _, test := range numberEqualToTests {
t.Run(test.name, func(t *testing.T) {
message := message.New().SetData(test.test)
insp, err := newNumberEqualTo(ctx, test.cfg)
if err != nil {
t.Fatal(err)
}

check, err := insp.Inspect(ctx, message)
if err != nil {
t.Error(err)
}

if test.expected != check {
t.Errorf("expected %v, got %v", test.expected, check)
t.Errorf("settings: %+v", test.cfg)
t.Errorf("test: %+v", string(test.test))
}
})
}
}

func benchmarkNumberEqualTo(b *testing.B, insp *numberEqualTo, message *message.Message) {
ctx := context.TODO()
for i := 0; i < b.N; i++ {
_, _ = insp.Inspect(ctx, message)
}
}

func BenchmarkNumberEqualTo(b *testing.B) {
for _, test := range numberEqualToTests {
insp, err := newNumberEqualTo(context.TODO(), test.cfg)
if err != nil {
b.Fatal(err)
}

b.Run(test.name,
func(b *testing.B) {
message := message.New().SetData(test.test)
benchmarkNumberEqualTo(b, insp, message)
},
)
}
}

0 comments on commit aa1d54e

Please sign in to comment.