Skip to content

Commit

Permalink
Merge pull request #403 from ysugimoto/feature/testing-assert-not-state
Browse files Browse the repository at this point in the history
implement assert.not_state assertion function
  • Loading branch information
ysugimoto authored Feb 1, 2025
2 parents 91fc939 + dc7ecff commit c8cf8ed
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 0 deletions.
17 changes: 17 additions & 0 deletions docs/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ We describe them following table and examples:
| assert.not_subroutine_called | FUNCTION | Assert subroutine has not called in testing subroutine |
| assert.restart | FUNCTION | Assert restart statement has called |
| assert.state | FUNCTION | Assert after state is expected one |
| assert.not_state | FUNCTION | Assert after state is not expected one |
| assert.error | FUNCTION | Assert error status code (and response) if error statement has called |
| assert.not_error | FUNCTION | Assert runtime state will not move to error status |

Expand Down Expand Up @@ -873,6 +874,22 @@ sub test_vcl {

----

### assert.not_state(ID state [, STRING message])

Assert current state is not expected one.

```vcl
sub test_vcl {
// vcl_recv will move state to lookup to lookup cache
testing.call_subroutine("vcl_recv");
// Assert state does not move to lookup
assert.not_state(lookup);
}
```

----

### assert.error(INTEGER status [, STRING response, STRING message])

Assert error status code (and response) if error statement has called.
Expand Down
51 changes: 51 additions & 0 deletions tester/function/assert_not_state.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package function

import (
"fmt"

"github.com/ysugimoto/falco/interpreter"
"github.com/ysugimoto/falco/interpreter/context"
"github.com/ysugimoto/falco/interpreter/function/errors"
"github.com/ysugimoto/falco/interpreter/value"
)

const Assert_not_state_Name = "assert.not_state"

var Assert_not_state_ArgumentTypes = []value.Type{value.IdentType}

func Assert_not_state_Validate(args []value.Value) error {
if len(args) > 2 {
return errors.ArgumentNotInRange(Assert_not_state_Name, 1, 2, args)
}

for i := range Assert_not_state_ArgumentTypes {
if args[i].Type() != Assert_not_state_ArgumentTypes[i] {
return errors.TypeMismatch(Assert_not_state_Name, i+1, Assert_not_state_ArgumentTypes[i], args[i].Type())
}
}

return nil
}

func Assert_not_state(
ctx *context.Context,
i *interpreter.Interpreter,
args ...value.Value,
) (value.Value, error) {

if err := Assert_not_state_Validate(args); err != nil {
return nil, errors.NewTestingError("%s", err.Error())
}

state := value.Unwrap[*value.Ident](args[0])
expect := interpreter.StateFromString(state.Value)

var message string
if len(args) == 2 {
message = value.Unwrap[*value.String](args[0]).Value
} else {
message = fmt.Sprintf("state should not be %s", expect)
}

return assert_not(state, expect.String(), i.TestingState.String(), message)
}
58 changes: 58 additions & 0 deletions tester/function/assert_not_state_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package function

import (
"testing"

"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/ysugimoto/falco/interpreter"
"github.com/ysugimoto/falco/interpreter/context"
"github.com/ysugimoto/falco/interpreter/function/errors"
"github.com/ysugimoto/falco/interpreter/value"
)

func Test_Assert_not_state(t *testing.T) {

tests := []struct {
args []value.Value
ip *interpreter.Interpreter
err error
expect *value.Boolean
}{
{
args: []value.Value{
&value.Ident{Value: "error"},
},
ip: &interpreter.Interpreter{
TestingState: interpreter.ERROR,
},
expect: &value.Boolean{Value: false},
err: &errors.AssertionError{},
},
{
args: []value.Value{
&value.Ident{Value: "error"},
},
ip: &interpreter.Interpreter{
TestingState: interpreter.LOOKUP,
},
expect: &value.Boolean{Value: true},
},
}

for i := range tests {
_, err := Assert_not_state(
&context.Context{},
tests[i].ip,
tests[i].args...,
)
if diff := cmp.Diff(
tests[i].err,
err,
cmpopts.IgnoreFields(errors.AssertionError{}, "Message", "Actual"),
cmpopts.IgnoreFields(errors.TestingError{}, "Message"),
); diff != "" {
t.Errorf("Assert_not_state()[%d] error: diff=%s", i, diff)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,26 @@ func assertionFunctions(i *interpreter.Interpreter, c Counter) Functions {
return false
},
},
"assert.not_state": {
Scope: allScope,
Call: func(ctx *context.Context, args ...value.Value) (value.Value, error) {
unwrapped, err := unwrapIdentArguments(i, args)
if err != nil {
return value.Null, errors.WithStack(err)
}
v, err := Assert_not_state(ctx, i, unwrapped...)
if err != nil {
c.Fail()
} else {
c.Pass()
}
return v, err
},
CanStatementCall: true,
IsIdentArgument: func(i int) bool {
return false
},
},
"assert.error": {
Scope: allScope,
Call: func(ctx *context.Context, args ...value.Value) (value.Value, error) {
Expand Down

0 comments on commit c8cf8ed

Please # to comment.