Skip to content

Commit

Permalink
feat(condition): Add Number Less Than Inspector (#186)
Browse files Browse the repository at this point in the history
* feat(condition): Add Number Less Than Inspector

* fix: less than type

* fix: less than condition

* fix: updated number.go

* refactor: no lint gocyclo
  • Loading branch information
Mallika05 authored Jun 21, 2024
1 parent ff966ba commit b949014
Show file tree
Hide file tree
Showing 5 changed files with 221 additions and 2 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,
},
lt(settings={}): $.condition.number.less_than(settings=settings),
less_than(settings={}): {
local default = $.condition.number.default,

type: 'number_less_than',
settings: std.prune(std.mergePatch(default, $.helpers.abbv(settings))),
},
gt(settings={}): $.condition.number.greater_than(settings=settings),
greater_than(settings={}): {
Expand Down
1 change: 1 addition & 0 deletions build/config/substation_test.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ local inspector = sub.condition.format.json();
{
condition: {
number: {
less_than: sub.condition.number.less_than({obj: {src: src}, value: 1}),
greater_than: sub.condition.number.greater_than({obj: {src: src}, value: 1}),
}
},
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_less_than":
return newNumberLessThan(ctx, cfg)
case "number_greater_than":
return newNumberGreaterThan(ctx, cfg)
case "number_bitwise_and":
Expand Down
51 changes: 51 additions & 0 deletions condition/number_less_than.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 newNumberLessThan(_ context.Context, cfg config.Config) (*numberLessThan, error) {
conf := numberConfig{}
if err := conf.Decode(cfg.Settings); err != nil {
return nil, err
}
insp := numberLessThan{
conf: conf,
}
return &insp, nil
}

type numberLessThan struct {
conf numberConfig
}

func (insp *numberLessThan) 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 *numberLessThan) match(f float64) bool {
return f < c.conf.Value
}

func (c *numberLessThan) String() string {
b, _ := json.Marshal(c.conf)
return string(b)
}
158 changes: 158 additions & 0 deletions condition/number_less_than_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 = &numberLessThan{}

var numberLessThanTests = []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":10}`),
true,
},
{
"fail",
config.Config{
Settings: map[string]interface{}{
"value": 1,
},
},
[]byte(`10`),
false,
},
{
"pass",
config.Config{
Settings: map[string]interface{}{
"object": map[string]interface{}{
"source_key": "foo",
},
"value": 10,
},
},
[]byte(`{"foo":1}`),
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.5,
},
},
[]byte(`{"foo":1.1}`),
true,
},
{
"pass",
config.Config{
Settings: map[string]interface{}{
"value": 1.5,
},
},
[]byte(`1`),
true,
},
}

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

for _, test := range numberLessThanTests {
t.Run(test.name, func(t *testing.T) {
message := message.New().SetData(test.test)
insp, err := newNumberLessThan(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 benchmarkNumberLessThan(b *testing.B, insp *numberLessThan, message *message.Message) {
ctx := context.TODO()
for i := 0; i < b.N; i++ {
_, _ = insp.Inspect(ctx, message)
}
}

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

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

0 comments on commit b949014

Please sign in to comment.