Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/inject value for tentative in simulator #344

Merged
merged 5 commits into from
Jul 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions ast/codec/declaration_decode.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package codec

import (
"github.com/k0kubun/pp"
"github.com/pkg/errors"
"github.com/ysugimoto/falco/ast"
)
Expand Down Expand Up @@ -203,7 +202,6 @@ func (c *Decoder) decodeDirectorBackendObject() (*ast.DirectorBackendObject, err
}
backend.Values = append(backend.Values, prop)
default:
pp.Println("OK")
return nil, typeMismatch(DIRECTOR_PROPERTY, frame.Type())
}
}
Expand Down
42 changes: 42 additions & 0 deletions cmd/falco/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"io"
"net/http"
"os"
"strconv"
"strings"

"github.com/fatih/color"
Expand Down Expand Up @@ -469,6 +470,25 @@ func (r *Runner) Test(rslv resolver.Resolver) (*tester.TestFactory, error) {
options = append(options, icontext.WithOverrideHost(tc.OverrideHost))
}

// Factory override variables.
// The order is imporotant, should do yaml -> cli order because cli could override yaml configuration
overrides := make(map[string]any)
if tc.YamlOverrideVariables != nil {
for key, val := range tc.YamlOverrideVariables {
overrides[key] = val
}
}
if tc.CLIOverrideVariables != nil {
for _, v := range tc.CLIOverrideVariables {
key, val, parsed := r.parseOverrideVariables(v)
if !parsed {
continue
}
overrides[key] = val
}
}
options = append(options, icontext.WithOverrideVariales(overrides))

r.message(white, "Running tests...")
factory, err := tester.New(tc, options).Run(r.config.Commands.At(1))
if err != nil {
Expand All @@ -480,6 +500,28 @@ func (r *Runner) Test(rslv resolver.Resolver) (*tester.TestFactory, error) {
return factory, nil
}

func (r *Runner) parseOverrideVariables(v string) (string, any, bool) {
sep := strings.SplitN(v, "=", 2)
if len(sep) != 2 {
return "", "", false
}
key := strings.TrimSpace(sep[0])
val := strings.TrimSpace(sep[1])

// Simple type assertion of primitive value
if strings.EqualFold(val, "true") {
return key, true, true // bool:true
} else if strings.EqualFold(val, "false") {
return key, false, true // bool:true
} else if v, err := strconv.ParseInt(val, 10, 64); err != nil {
return key, v, true // integer
} else if v, err := strconv.ParseFloat(val, 64); err != nil {
return key, v, true // float
} else {
return key, val, true // string
}
}

func (r *Runner) Format(rslv resolver.Resolver) error {
main, err := rslv.MainVCL()
if err != nil {
Expand Down
15 changes: 15 additions & 0 deletions cmd/falco/runner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,12 @@ func TestTester(t *testing.T) {
filter: "*mock_subroutine.test.vcl",
passes: 6,
},
{
name: "overriding variables test",
main: "../../examples/testing/override_variables.vcl",
filter: "*override_variables.test.vcl",
passes: 6,
},
}

for _, tt := range tests {
Expand All @@ -367,6 +373,15 @@ func TestTester(t *testing.T) {
},
Testing: &config.TestConfig{
Filter: tt.filter,
YamlOverrideVariables: map[string]any{
"tls.client.certificate.is_cert_missing": true,
"client.geo.area_code": 100,
"req.digest.ratio": 0.8,
"client.as.name": "Foobar",
},
CLIOverrideVariables: []string{
"client.geo.area_code=200", // will be overridden
},
},
Commands: config.Commands{"test", main},
}
Expand Down
7 changes: 7 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ type SimulatorConfig struct {

// Override Request configuration
OverrideRequest *RequestConfig

// Inject values that the simulator returns tentative value
InjectValues map[string]any `yaml:"values"`
}

// Testing configuration
Expand All @@ -67,6 +70,10 @@ type TestConfig struct {

// Override Request configuration
OverrideRequest *RequestConfig

// Override tentative variable values
CLIOverrideVariables []string `cli:"o,override"` // from CLI
YamlOverrideVariables map[string]any `yaml:"overrides"` // from .falco.yaml
}

// Console configuration
Expand Down
2 changes: 1 addition & 1 deletion docs/rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -908,7 +908,7 @@ Failed to load include target module.

## regex/matched-value-override

Regex matched operator `re.group.N` value will be overriden.
Regex matched operator `re.group.N` value will be overridden.

These variables could use if(else) block statement when condition has regex operator like `~` or `!~`.
Note that group matched variable has potential of making bugs due to its spec:
Expand Down
33 changes: 28 additions & 5 deletions docs/variables.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,28 @@
# Variables in simulator

Following table describes variables that will return tentative values.
Will be updated when we find or implement a way to get accurate values.
Following table describes variables that will return tentative values,
but you can override these values by configuration or cli arguments for testing.

## Overide by Configuration

Put override configuration in `testing.overrides` section as map.

```yaml
...
testing:
overrides:
client.class.checker: true
client.as.name: "overridden"
...
```

## CLI

Provide `-o, --override` option on the CLI command, accepts multiple options.

```shell
falco test /path/to/main.vcl -o "client.class.checker=true" -o "client.as.name=overridden"
```


| Variable | Tentative Value |
Expand All @@ -15,8 +36,8 @@ Will be updated when we find or implement a way to get accurate values.
| client.platform.mediaplayer | false |
| client.geo.latitude | 37.7786941 |
| client.geo.longitude | -122.3981452 |
| client.as_number | 4294967294 |
| client.as_name | "Reserved" |
| client.as.number | 4294967294 |
| client.as.name | "Reserved" |
| client.display.height | -1 |
| client.display.ppi | -1 |
| client.display.width | -1 |
Expand Down Expand Up @@ -67,7 +88,7 @@ Will be updated when we find or implement a way to get accurate values.
| obj.is_pci | false |
| req.backend.is_cluster | false |
| resp.is_locally_generated | false |
| req.digest_ratio | 0.4 |
| req.digest.ratio | 0.4 |
| obj.stale_white_revalidate | 60s |
| backend.socket.congestion_algorithm | "cubic" |
| backend.socket.cwnd | 60 |
Expand Down Expand Up @@ -184,3 +205,5 @@ Will be updated when we find or implement a way to get accurate values.

"TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8:TLS_ECDHE_ECDSA_WITH_AES_256_CCM:TLS_DHE_RSA_WITH_AES_256_CCM_8:TLS_DHE_RSA_WITH_AES_256_CCM:TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384:TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384:TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384:TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384:TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:TLS_ECDHE_ECDSA_WITH_AES_128_CCM:TLS_DHE_RSA_WITH_AES_128_CCM_8:TLS_DHE_RSA_WITH_AES_128_CCM:TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256:TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256:TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256:TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256:TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:TLS_DHE_RSA_WITH_AES_256_CBC_SHA:TLS_DHE_DSS_WITH_AES_256_CBC_SHA:TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:TLS_DHE_RSA_WITH_AES_128_CBC_SHA:TLS_DHE_DSS_WITH_AES_128_CBC_SHA:TLS_RSA_WITH_AES_256_GCM_SHA384:TLS_RSA_WITH_AES_256_CCM_8:TLS_RSA_WITH_AES_256_CCM:TLS_RSA_WITH_ARIA_256_GCM_SHA384:TLS_RSA_WITH_AES_128_GCM_SHA256:TLS_RSA_WITH_AES_128_CCM_8:TLS_RSA_WITH_AES_128_CCM:TLS_RSA_WITH_ARIA_128_GCM_SHA256:TLS_RSA_WITH_AES_256_CBC_SHA256:TLS_RSA_WITH_AES_128_CBC_SHA256:TLS_RSA_WITH_AES_256_CBC_SHA:TLS_RSA_WITH_AES_128_CBC_SHA:TLS_EMPTY_RENEGOTIATION_INFO_SCSV"
```

These values will be updated when we find or implement a way to get accurate values.
32 changes: 32 additions & 0 deletions examples/testing/override_variables.test.vcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// @scope: recv
// @suite: Default variable via function
sub test_default_server_region {
testing.call_subroutine("vcl_recv");

assert.equal(req.http.Region, "US");
}

// @scope: recv
// @suite: Override variable via function
sub test_override_server_region {
testing.inject_variable("server.region", "ASIA");
testing.call_subroutine("vcl_recv");

assert.equal(req.http.Region, "ASIA");
}

// @scope: deliver
// @suite: Assert overridden variables via configuration
sub test_override_via_configuration {
testing.call_subroutine("overrides");

// bool
assert.equal(req.http.Is-Cert-Bad, "1");
// integer
assert.equal(req.http.Geo-Area-Code, "200");
// float
assert.equal(req.http.Digest-Ratio, "0.800");
// string
assert.equal(req.http.Client-As-Name, "Foobar");
}

13 changes: 13 additions & 0 deletions examples/testing/override_variables.vcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
sub vcl_recv {
#Fastly recv
set req.http.Region = server.region;
}


sub overrides {
// Following variables could be overridden by configuration
set req.http.Is-Cert-Bad = tls.client.certificate.is_cert_missing;
set req.http.Geo-Area-Code = client.geo.area_code;
set req.http.Digest-Ratio = req.digest.ratio;
set req.http.Client-As-Name = client.as.name;
}
4 changes: 4 additions & 0 deletions interpreter/context/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,8 @@ type Context struct {
// However, Fastly document says the esi will be triggered when esi statement is executed in FETCH directive.
// see: https://developer.fastly.com/reference/vcl/statements/esi/
TriggerESI bool

OverrideVariables map[string]value.Value
}

func New(options ...Option) *Context {
Expand Down Expand Up @@ -258,6 +260,8 @@ func New(options ...Option) *Context {

RegexMatchedValues: make(map[string]*value.String),
SubroutineCalls: make(map[string]int),

OverrideVariables: make(map[string]value.Value),
}

// collect options
Expand Down
18 changes: 18 additions & 0 deletions interpreter/context/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package context

import (
"github.com/ysugimoto/falco/config"
"github.com/ysugimoto/falco/interpreter/value"
"github.com/ysugimoto/falco/resolver"
"github.com/ysugimoto/falco/snippets"
)
Expand Down Expand Up @@ -61,3 +62,20 @@ func WithActualResponse(is bool) Option {
c.IsActualResponse = is
}
}

func WithOverrideVariales(variables map[string]any) Option {
return func(c *Context) {
for k, v := range variables {
switch t := v.(type) {
case int:
c.OverrideVariables[k] = &value.Integer{Value: int64(t)}
case string:
c.OverrideVariables[k] = &value.String{Value: t}
case float64:
c.OverrideVariables[k] = &value.Float{Value: float64(t)}
case bool:
c.OverrideVariables[k] = &value.Boolean{Value: t}
}
}
}
}
4 changes: 0 additions & 4 deletions interpreter/statement.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"io"
"strings"

"github.com/k0kubun/pp"
"github.com/pkg/errors"
"github.com/ysugimoto/falco/ast"
"github.com/ysugimoto/falco/interpreter/assign"
Expand Down Expand Up @@ -37,9 +36,6 @@ func (i *Interpreter) ProcessBlockStatement(
}

// Find process marker and add flow if found
if stmt.GetMeta() == nil {
pp.Println(stmt)
}
if name, found := findProcessMark(stmt.GetMeta().Leading); found {
i.process.Flows = append(
i.process.Flows,
Expand Down
Loading