Skip to content

Commit

Permalink
added integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
magnusgohn committed Mar 22, 2024
1 parent a1facc5 commit 3664e37
Show file tree
Hide file tree
Showing 13 changed files with 986 additions and 14 deletions.
Binary file added .DS_Store
Binary file not shown.
31 changes: 31 additions & 0 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ on:
pull_request:
branches:
- main

jobs:
test:
name: Test
Expand Down Expand Up @@ -45,3 +46,33 @@ jobs:

- name: Test example/devdata_cli (sub module)
run: cd ./examples/devdata_cli && go test -race ./...

integration_test:
name: Integration test
strategy:
matrix:
# boolean values are cast to indices
environments: ${{ fromJSON('[["staging"], ["staging", "production"]]')[github.ref == 'refs/heads/main'] }}
runs-on: ubuntu-latest
environment: ${{ matrix.environments }}
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0 # Required for go-header check.

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version-file: go.mod
cache-dependency-path: |
go.sum
examples/devdata_cli/go.sum
id: go

- name: Test (main module)
run: go test -v -race ./test/...
env:
CLARIFY_USERNAME: ${{ secrets.CLARIFY_USERNAME }}
CLARIFY_PASSWORD: ${{ secrets.CLARIFY_PASSWORD }}
CLARIFY_ENDPOINT: ${{ secrets.CLARIFY_ENDPOINT }}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ By using our [automation](automation) and [automationcli](automation/automationc

## Copyright

Copyright 2022-2023 Searis AS
Copyright 2022-2024 Searis AS

Licensed under the Apache License, Version 2.0 (the "License");
you may not use the content in this repo except in compliance with the License.
Expand Down
13 changes: 10 additions & 3 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,14 +298,20 @@ func (er EvaluateRequest) Include(relationships ...string) EvaluateRequest {
return er
}

func (er EvaluateRequest) Format(format views.SelectionFormat) EvaluateRequest {
er.format = format

return er
}

func (er EvaluateRequest) Do(ctx context.Context) (*EvaluateResult, error) {
r := methodEvaluate.NewRequest(er.h,
paramData.Value(er.data),
paramItems.Value(er.items),
paramGroups.Value(er.groups),
paramCalculations.Value(er.calculations))

r.Include(er.relationships...)
paramCalculations.Value(er.calculations),
paramFormat.Value(er.format)).
Include(er.relationships...)

return r.Do(ctx)
}
Expand All @@ -318,6 +324,7 @@ type EvaluateRequest struct {
groups []fields.EvaluateGroup
calculations []fields.Calculation
relationships []string
format views.SelectionFormat
h jsonrpc.Handler
}

Expand Down
27 changes: 17 additions & 10 deletions fields/evaluate.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,17 +193,24 @@ func (ei EvaluateItem) MarshalJSON() ([]byte, error) {
func (eg EvaluateGroup) MarshalJSON() ([]byte, error) {
var v any

type encType struct {
Alias string `json:"alias,omitempty"`
Query ResourceQuery `json:"query,omitempty"`
TimeAggregation TimeAggregation `json:"timeAggregation,omitempty"`
GroupAggregation GroupAggregation `json:"groupAggregation,omitempty"`
State int `json:"-"`
Lead int `json:"lead,omitempty"`
Lag int `json:"lag,omitempty"`
}
switch eg.TimeAggregation {
case TimeAggregationSeconds, TimeAggregationPercent, TimeAggregationRate:
type encType EvaluateGroup

v = encType(eg)
v = encType(eg)
default:
type encType struct {
Alias string `json:"alias,omitempty"`
Query ResourceQuery `json:"query,omitempty"`
TimeAggregation TimeAggregation `json:"timeAggregation,omitempty"`
GroupAggregation GroupAggregation `json:"groupAggregation,omitempty"`
State int `json:"-"`
Lead int `json:"lead,omitempty"`
Lag int `json:"lag,omitempty"`
}

v = encType(eg)
}

return json.Marshal(v)
}
Expand Down
146 changes: 146 additions & 0 deletions test/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
// Copyright 2024 Searis AS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package test

import (
"context"
"encoding/json"
"os"
"runtime"
"strings"
"testing"
"time"

"github.com/clarify/clarify-go"
"github.com/clarify/clarify-go/fields"
)

const (
AnnotationKey = "there-is-always-money"
AnnotationValue = "in-the-banana-stand"
)

func getDefaultTimeRange() (time.Time, time.Time) {
tidenesMorgen := time.Unix(0, 0).UTC().Truncate(time.Hour)
tidenesKveld := tidenesMorgen.Add(10 * time.Hour)

return tidenesMorgen, tidenesKveld
}

func testName() string {
pc := make([]uintptr, 10)
n := runtime.Callers(3, pc)
frame, _ := runtime.CallersFrames(pc[:n]).Next()
funks := strings.Split(frame.Function, ".")
funk := funks[len(funks)-1]

return funk
}

func createPrefix() string {
test := testName()

return test + "/"
}

func getCredentials(t *testing.T) *clarify.Credentials {
var creds *clarify.Credentials

username := os.Getenv("CLARIFY_USERNAME")
password := os.Getenv("CLARIFY_PASSWORD")
endpoint := os.Getenv("CLARIFY_ENDPOINT")
credentials := os.Getenv("CLARIFY_CREDENTIALS")

switch {
case username != "" && password != "":
creds = clarify.BasicAuthCredentials(username, password)

if endpoint != "" {
creds.APIURL = endpoint
}
case credentials != "":
var err error
creds, err = clarify.CredentialsFromFile(credentials)
if err != nil {
t.Fatalf("failed to parse credentials file: %s", err)
}
default:
t.Skip("no credentials found, skipping integration tests")
}

if err := creds.Validate(); err != nil {
t.Fatalf("invalid credentials: %s", err)
}

return creds
}

func jsonEncode[v any](t *testing.T, a v) {
enc := json.NewEncoder(os.Stdout)

enc.SetIndent("", " ")

err := enc.Encode(a)
if err != nil {
t.Errorf("%v", err)
}
}

func createAnnotationQuery(prefix string) fields.ResourceQuery {
return fields.Query().
Where(fields.Comparisons{"annotations." + prefix + AnnotationKey: fields.Equal(AnnotationValue)}).
Limit(10)
}

func onlyError[R any](f func(TestArgs) (R, error)) func(TestArgs) error {
return func(a TestArgs) error {
_, err := f(a)

return err
}
}

func applyTestArgs(a TestArgs, fs ...func(a TestArgs) error) {
for _, f := range fs {
if err := f(a); err != nil {
panic(err)
}
}
}

type TestArgs struct {
ctx context.Context
integration string
client *clarify.Client
prefix string
}

func Map[A any, B any](f func(a A) B, as []A) []B {
g := func(index int, a A) B {
return f(a)
}

return MapIndex(g, as)
}

func MapIndex[A any, B any](f func(i int, a A) B, as []A) []B {
bs := make([]B, len(as))

for i := range as {
bs[i] = f(i, as[i])
}

return bs
}
98 changes: 98 additions & 0 deletions test/data_frame_integration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// Copyright 2024 Searis AS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package test

import (
"context"
"testing"
"time"

clarify "github.com/clarify/clarify-go"
"github.com/clarify/clarify-go/fields"
)

func TestDataFrame(t *testing.T) {
ctx := context.Background()
creds := getCredentials(t)
client := creds.Client(ctx)
prefix := createPrefix()
a := TestArgs{
ctx: ctx,
integration: creds.Integration,
client: client,
prefix: prefix,
}

applyTestArgs(a, onlyError(insertDefault), onlyError(saveSignalsDefault), onlyError(publishSignalsDefault))

t0, t1 := getDefaultTimeRange()

type testCase struct {
testArgs TestArgs
items fields.ResourceQuery
data fields.DataQuery
expectedFields func(*clarify.DataFrameResult) bool
}

test := func(tc testCase) func(t *testing.T) {
return func(t *testing.T) {
t.Helper()

result, err := dataFrame(tc.testArgs.ctx, tc.testArgs.client, tc.items, tc.data)
if err != nil {
t.Errorf("Unexpected error: %v", err)
} else if !tc.expectedFields(result) {
t.Errorf("unexpected field found!")
}

jsonEncode(t, result)
}
}

t.Run("basic data frame test", test(testCase{
testArgs: a,
items: createAnnotationQuery(a.prefix),
data: fields.Data().Where(fields.TimeRange(t0, t1)).RollupDuration(time.Hour, time.Monday),
expectedFields: func(dfr *clarify.DataFrameResult) bool {
return true
},
}))

t.Run("less basic data frame test", test(testCase{
testArgs: a,
items: createAnnotationQuery(a.prefix),
data: fields.Data().Where(fields.TimeRange(t1, t0)).RollupDuration(time.Hour, time.Monday),
expectedFields: func(dfr *clarify.DataFrameResult) bool {
return true
},
}))
}

func dataFrame(ctx context.Context, client *clarify.Client, items fields.ResourceQuery, data fields.DataQuery) (*clarify.DataFrameResult, error) {
result, err := client.Clarify().DataFrame(items, data).Do(ctx)

return result, err
}

//lint:ignore U1000 Ignore unused function temporarily for debugging
func dataFrameDefault(a TestArgs) (*clarify.DataFrameResult, error) {
items := createAnnotationQuery(a.prefix)
t0, t1 := getDefaultTimeRange()
data := fields.Data().
Where(fields.TimeRange(t0, t1)).
RollupDuration(time.Hour, time.Monday)

return dataFrame(a.ctx, a.client, items, data)
}
Loading

0 comments on commit 3664e37

Please sign in to comment.