Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into feature/implement-codec
Browse files Browse the repository at this point in the history
  • Loading branch information
ysugimoto committed Jun 9, 2024
2 parents f37f53f + 673ed3e commit 9f997f9
Show file tree
Hide file tree
Showing 29 changed files with 1,093 additions and 39 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v4
with:
Expand All @@ -23,9 +23,9 @@ jobs:
make plugin_ci
make test
- name: Lint programs
uses: golangci/golangci-lint-action@v5
uses: golangci/golangci-lint-action@v6
with:
version: v1.58
skip-pkg-cache: true
skip-build-cache: true
skip-go-installation: true
skip-cache: true
skip-save-cache: true
install-mode: binary
10 changes: 5 additions & 5 deletions .github/workflows/pullrequest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: 1.22.2
- name: Run tests
run: make test
- name: Lint programs
uses: golangci/golangci-lint-action@v5
uses: golangci/golangci-lint-action@v6
with:
version: v1.58
skip-pkg-cache: true
skip-build-cache: true
skip-go-installation: true
skip-cache: true
skip-save-cache: true
install-mode: binary
10 changes: 5 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,20 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: 1.22.2
- name: Run tests
run: make test
- name: Lint programs
uses: golangci/golangci-lint-action@v5
uses: golangci/golangci-lint-action@v6
with:
version: v1.58
skip-pkg-cache: true
skip-build-cache: true
skip-go-installation: true
skip-cache: true
skip-save-cache: true
install-mode: binary
- name: Set version
id: version
run: |
Expand Down
4 changes: 4 additions & 0 deletions cmd/falco/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,10 @@ func (r *Runner) Simulate(rslv resolver.Resolver) error {
if r.config.OverrideBackends != nil {
options = append(options, icontext.WithOverrideBackends(r.config.OverrideBackends))
}
// If simulator configuration has edge dictionaries, inject them
if sc.OverrideEdgeDictionaries != nil {
options = append(options, icontext.WithInjectEdgeDictionaries(sc.OverrideEdgeDictionaries))
}

i := interpreter.New(options...)

Expand Down
6 changes: 6 additions & 0 deletions cmd/falco/runner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,12 @@ func TestTester(t *testing.T) {
filter: "*group.test.vcl",
passes: 3,
},
{
name: "mockging test",
main: "../../examples/testing/mock_subroutine.vcl",
filter: "*mock_subroutine.test.vcl",
passes: 6,
},
}

for _, tt := range tests {
Expand Down
5 changes: 5 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ type OverrideBackend struct {
Unhealthy bool `yaml:"unhealthy" default:"false"`
}

type EdgeDictionary map[string]string

// Linter configuration
type LinterConfig struct {
VerboseLevel string `yaml:"verbose"`
Expand All @@ -47,6 +49,9 @@ type SimulatorConfig struct {
KeyFile string `cli:"key" yaml:"key_file"`
CertFile string `cli:"cert" yaml:"cert_file"`

// Inject Edge Dictionary items
OverrideEdgeDictionaries map[string]EdgeDictionary `yaml:"edge_dictionary"`

// Override Request configuration
OverrideRequest *RequestConfig
}
Expand Down
8 changes: 8 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ simulator:
max_acls: 100
key_file: /path/to/key_file.pem
cert_file: /path/to/cert_file.pem
edge_dictionary:
dict_name:
key1: value1
key2: value2

## Testing configuration
testing:
Expand All @@ -55,6 +59,10 @@ All configurations of configuration files and CLI arguments are described follow
| max_acls | Integer | 1000 | --max_acls | Override Fastly's acl amount limitation |
| simulator | Object | null | - | Simulator configuration object |
| simulator.port | Integer | 3124 | -p, --port | Simulator server listen port |
| simulator.key_file | String | - | --key | TLS server key file path |
| simulator.cert_file | String | - | --cert | TLS server cert file path |
| simulator.edge_dictionary | Object | null | - | Local edge dictionary item definitions |
| simulator.edge_dictionary.[name] | Object | - | - | Local edge dictionary name |
| testing | Object | null | - | Testing configuration object |
| testing.timeout | Integer | 10 | -t, --timeout | Set timeout to stop testing |
| linter | Object | null | - | Override linter rules |
Expand Down
7 changes: 7 additions & 0 deletions docs/simulator.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,13 @@ falco simulate /path/to/your/default.vcl --key /path/to/localhost-key.pem --cert

Then falco serve with https://localhost:3124.

## Override Edge Dictionary Items

Edge Dictionary values are managed in Fastly cloud but often we have some logics that relates to its value (e.g flag true/false), and write-only dictionary items could access via remote API.
To simulate its behavior with specific value, falco supports overriding edge dictionary item locally from configuration.

See `simulator.edge_dictionary` field in [configuration.md](./configuration.md).

## Debug mode

`falco` also includes TUI debugger so that you can debug VCL with step execution.
Expand Down
122 changes: 122 additions & 0 deletions docs/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,9 @@ We describe them following table and examples:
| testing.inspect | FUNCTION | Inspect predefined variables for any scopes |
| testing.table_set | FUNCTION | Inject value for key to main VCL table |
| testing.table_merge | FUNCTION | Merge values from testing VCL table to main VCL table |
| testing.mock | FUNCTION | Mock the subroutine with specified subroutine in the testing VCL |
| testing.resotre_mock | FUNCTION | Restore specific mocked subroutine |
| testing.restore_all_mocks | FUNCTION | Restore all mocked subroutines |
| assert | FUNCTION | Assert provided expression should be true |
| assert.true | FUNCTION | Assert actual value should be true |
| assert.false | FUNCTION | Assert actual value should be false |
Expand Down Expand Up @@ -353,6 +356,125 @@ sub test_vcl {

----

### testing.mock(STRING from, STRING to)

Mock the subroutine with testing subroutine.

> [!NOTE]
> You cannot mock Fastly reserved (lifecycle) subroutine that starts with `vcl_` like `vcl_recv`, `vcl_fetch`, etc.
> But you can mock the functional subroutine that returns some value.
```vcl
sub mock_add_header {
set req.http.Mocked = "1";
}
// @scope: recv
sub test_vcl {
// Mock the subroutine
testing.mock("add_header", "mock_add_header");
// vcl_recv has a dependency that calls "add_header" subroutine inside.
testing.call_subroutine("vcl_recv");
// Assert mocked subroutine result
assert.equal(req.http.Mocked, "1");
}
```

----

### testing.restore_mock(STRING from)

Restore mocked subroutine to the original.
Normally This function is used inside `describe` grouped testing hooks.

```vcl
sub mock_add_header {
set req.http.Mocked = "1";
}
describe add_header_mock {
sub before_recv {
// Mock subroutine
testing.mock("add_header", "mock_add_header");
}
sub after_recv {
// Restore mock
testing.restore_mock("add_header");
}
// @scope: recv
sub test_vcl {
// Mock the subroutine
testing.mock("add_header", "mock_add_header");
// vcl_recv has a dependency that calls "add_header" subroutine inside.
testing.call_subroutine("vcl_recv");
// Assert mocked subroutine result
assert.equal(req.http.Mocked, "1");
}
// @scope: fetch
sub test_fetch {
// This subroutine no longer uses mocked subroutine
...
}
}
```

----

### testing.restore_all_mocks()

Restore all mocked subroutines.
Normally This function is used inside `describe` grouped testing hooks.

```vcl
sub mock_add_header {
set req.http.Mocked = "1";
}
describe add_header_mock {
sub before_recv {
// Mock subroutine
testing.mock("add_header", "mock_add_header");
}
sub after_recv {
// Restore all mocks
testing.restore_all_mocks();
}
// @scope: recv
sub test_vcl {
// Mock the subroutine
testing.mock("add_header", "mock_add_header");
// vcl_recv has a dependency that calls "add_header" subroutine inside.
testing.call_subroutine("vcl_recv");
// Assert mocked subroutine result
assert.equal(req.http.Mocked, "1");
}
// @scope: fetch
sub test_fetch {
// This subroutine no longer uses mocked subroutine
...
}
}
```

----

### assert(ANY expr [, STRING message])

Assert provided expression should be truthy.
Expand Down
4 changes: 4 additions & 0 deletions examples/simulator/simulator.vcl
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,16 @@ backend example_com {
}
}

table injectable_dict STRING {
}

sub vcl_recv {

#Fastly recv
// @debugger
set req.backend = example_com;
set req.http.Foo = {" foo bar baz "};
set req.http.Item = table.lookup(injectable_dict, "virtual");
call custom_logger;
return (pass);
}
Expand Down
37 changes: 37 additions & 0 deletions examples/testing/mock_subroutine.test.vcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
sub mocked {
set req.http.Mocked = "1";
}

sub mocked_func STRING {
return "Mocked";
}

describe group {

before_recv {
testing.mock("original", "mocked");
testing.mock("original_func", "mocked_func");
}

after_recv {
testing.restore_all_mocks();
unset req.http.Mocked;
}

// @scope: recv
sub test_recv {
testing.call_subroutine("vcl_recv");
assert.equal(req.http.Mocked, "1");
assert.is_notset(req.http.Original);
assert.equal(req.http.FuncValue, "Mocked");
}

// @scope: fetch
sub test_fetch {
testing.call_subroutine("vcl_fetch");
assert.equal(req.http.Original, "1");
assert.is_notset(req.http.Mocked);
assert.equal(req.http.FuncValue, "Original");
}

}
21 changes: 21 additions & 0 deletions examples/testing/mock_subroutine.vcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// @scope: recv,fetch
sub original {
set req.http.Original = "1";
}

// @scope: recv,fetch
sub original_func STRING {
return "Original";
}

sub vcl_recv {
#FASTLY RECV
call original;
set req.http.FuncValue = original_func();
}

sub vcl_fetch {
#FASTLY FETCH
call original;
set req.http.FuncValue = original_func();
}
Loading

0 comments on commit 9f997f9

Please sign in to comment.