diff --git a/.run/build.run.xml b/.run/build.run.xml
new file mode 100644
index 00000000..cc73411b
--- /dev/null
+++ b/.run/build.run.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/format.run.xml b/.run/format.run.xml
index 64e3c038..6742b4d0 100644
--- a/.run/format.run.xml
+++ b/.run/format.run.xml
@@ -1,7 +1,8 @@
-
-
-
-
-
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/gofmt.run.xml b/.run/gofmt.run.xml
deleted file mode 100644
index dad3de0b..00000000
--- a/.run/gofmt.run.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/go.mod b/go.mod
index 2b681cc1..2cd8fdf9 100644
--- a/go.mod
+++ b/go.mod
@@ -22,6 +22,7 @@ require (
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.19.0
github.com/stretchr/testify v1.9.0
+ github.com/xeipuuv/gojsonschema v1.2.0
golang.org/x/net v0.26.0
)
@@ -34,6 +35,8 @@ require (
github.com/sagikazarmark/locafero v0.6.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
+ github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
+ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
go.uber.org/multierr v1.11.0 // indirect
)
@@ -53,5 +56,5 @@ require (
golang.org/x/sys v0.21.0 // indirect
golang.org/x/text v0.16.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
- gopkg.in/yaml.v3 v3.0.1 // indirect
+ gopkg.in/yaml.v3 v3.0.1
)
diff --git a/go.sum b/go.sum
index c52cba3e..515037f5 100644
--- a/go.sum
+++ b/go.sum
@@ -88,6 +88,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
@@ -95,6 +96,12 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
+github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
+github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
+github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
+github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
+github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
+github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY=
diff --git a/makefile b/makefile
index df6cb34c..50345494 100644
--- a/makefile
+++ b/makefile
@@ -8,7 +8,7 @@ update_deps:
go mod tidy
test:
- go test -v ./...
+ go test ./...
test-cover:
go test -tags release -timeout 1m -race -v -coverprofile=coverage.out ./...
@@ -17,4 +17,7 @@ build:
go build ./...
build-release:
- go build -tags release ./...
\ No newline at end of file
+ go build -tags release ./...
+
+clean:
+ rm -rf ./uncors ./uncors.exe coverage.out
\ No newline at end of file
diff --git a/testing/testutils/fs.go b/testing/testutils/fs.go
index 6dd2fff1..6fedb1f0 100644
--- a/testing/testutils/fs.go
+++ b/testing/testutils/fs.go
@@ -2,8 +2,12 @@ package testutils
import (
"os"
+ "path/filepath"
+ "runtime"
"testing"
+ "github.com/stretchr/testify/require"
+
"github.com/spf13/afero"
)
@@ -22,3 +26,11 @@ func FsFromMap(t *testing.T, files map[string]string) afero.Fs {
return fs
}
+
+func CurrentDir(t *testing.T) string {
+ t.Helper()
+ _, callerFile, _, ok := runtime.Caller(1)
+ require.True(t, ok, "Failed to get caller information")
+
+ return filepath.Dir(callerFile)
+}
diff --git a/tests/schema/helpers.go b/tests/schema/helpers.go
new file mode 100644
index 00000000..d4b455e9
--- /dev/null
+++ b/tests/schema/helpers.go
@@ -0,0 +1,42 @@
+package schema
+
+import (
+ "encoding/json"
+ "os"
+ "path/filepath"
+ "strings"
+ "testing"
+
+ "github.com/evg4b/uncors/testing/testutils"
+ "github.com/stretchr/testify/require"
+ "gopkg.in/yaml.v3"
+)
+
+func TransformToJSON(t *testing.T, dir string, file string) string {
+ t.Helper()
+ yamlFilePath := filepath.Join(testutils.CurrentDir(t), file)
+ jsonFilePath := filepath.Join(dir, strings.Replace(filepath.Base(file), ".yaml", ".json", 1))
+
+ yamlFile, err := os.OpenFile(yamlFilePath, os.O_RDONLY, os.ModePerm)
+ require.NoError(t, err, "Failed to open file: %v", err)
+ defer yamlFile.Close()
+
+ jsonFile, err := os.OpenFile(jsonFilePath, os.O_CREATE|os.O_WRONLY, os.ModePerm)
+ require.NoError(t, err, "Failed to open file: %v", err)
+ defer yamlFile.Close()
+
+ var data any
+ err = yaml.NewDecoder(yamlFile).Decode(&data)
+ require.NoError(t, err, "Failed to decode yaml: %v", err)
+
+ err = json.NewEncoder(jsonFile).Encode(data)
+ require.NoError(t, err, "Failed to encode json: %v", err)
+
+ return jsonFilePath
+}
+
+func DirPredicate(dir string) func(string) string {
+ return func(file string) string {
+ return filepath.Join(dir, file)
+ }
+}
diff --git a/tests/schema/invalid/empty-mappings.yaml b/tests/schema/invalid/empty-mappings.yaml
new file mode 100644
index 00000000..b20135dd
--- /dev/null
+++ b/tests/schema/invalid/empty-mappings.yaml
@@ -0,0 +1 @@
+mappings: []
\ No newline at end of file
diff --git a/tests/schema/invalid/not-full-mapping.yaml b/tests/schema/invalid/not-full-mapping.yaml
new file mode 100644
index 00000000..7d42a511
--- /dev/null
+++ b/tests/schema/invalid/not-full-mapping.yaml
@@ -0,0 +1,3 @@
+mappings:
+ - from: http://localhost
+ to:
diff --git a/tests/schema/invalid_test.go b/tests/schema/invalid_test.go
new file mode 100644
index 00000000..b8620c60
--- /dev/null
+++ b/tests/schema/invalid_test.go
@@ -0,0 +1,61 @@
+package schema_test
+
+import (
+ "path/filepath"
+ "testing"
+
+ "github.com/evg4b/uncors/tests/schema"
+
+ "github.com/evg4b/uncors/testing/testutils"
+ "github.com/samber/lo"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+ "github.com/xeipuuv/gojsonschema"
+)
+
+func TestInvalidJsonSchema(t *testing.T) {
+ testdir := schema.DirPredicate("invalid")
+
+ testTempDir := t.TempDir()
+ jsonSchemaPath := filepath.Join(testutils.CurrentDir(t), "../../schema.json")
+
+ cases := []struct {
+ name string
+ file string
+ errors []string
+ }{
+ {
+ name: "empty mappings",
+ file: testdir("empty-mappings.yaml"),
+ errors: []string{
+ "mappings: Array must have at least 1 items",
+ },
+ },
+ {
+ name: "not full mapping",
+ file: testdir("not-full-mapping.yaml"),
+ errors: []string{
+ "mappings.0: Must validate one and only one schema (oneOf)",
+ "mappings.0.to: Invalid type. Expected: string, given: null",
+ },
+ },
+ }
+
+ for _, testCase := range cases {
+ t.Run(testCase.name, func(t *testing.T) {
+ targetJSONFile := schema.TransformToJSON(t, testTempDir, testCase.file)
+
+ schemaLoader := gojsonschema.NewReferenceLoader("file://" + jsonSchemaPath)
+ documentLoader := gojsonschema.NewReferenceLoader("file://" + targetJSONFile)
+
+ result, err := gojsonschema.Validate(schemaLoader, documentLoader)
+ require.NoError(t, err)
+
+ errors := lo.Map(result.Errors(), func(err gojsonschema.ResultError, _ int) string {
+ return err.String()
+ })
+
+ assert.Equal(t, testCase.errors, errors, "The errors are not as expected")
+ })
+ }
+}
diff --git a/tests/schema/valid/minimal-valid.yaml b/tests/schema/valid/minimal-valid.yaml
new file mode 100644
index 00000000..7396b730
--- /dev/null
+++ b/tests/schema/valid/minimal-valid.yaml
@@ -0,0 +1,3 @@
+mappings:
+ - from: http://localhost
+ to: https://github.com
\ No newline at end of file
diff --git a/tests/schema/valid/short-mapping.yaml b/tests/schema/valid/short-mapping.yaml
new file mode 100644
index 00000000..ef695731
--- /dev/null
+++ b/tests/schema/valid/short-mapping.yaml
@@ -0,0 +1,3 @@
+http-port: 3000
+mappings:
+ - http://localhost: https://github.com
\ No newline at end of file
diff --git a/tests/schema/valid_test.go b/tests/schema/valid_test.go
new file mode 100644
index 00000000..03f5ffd8
--- /dev/null
+++ b/tests/schema/valid_test.go
@@ -0,0 +1,50 @@
+package schema_test
+
+import (
+ "path/filepath"
+ "testing"
+
+ "github.com/evg4b/uncors/tests/schema"
+
+ "github.com/evg4b/uncors/testing/testutils"
+
+ "github.com/stretchr/testify/assert"
+
+ "github.com/stretchr/testify/require"
+ "github.com/xeipuuv/gojsonschema"
+)
+
+func TestValidJsonSchema(t *testing.T) {
+ testdir := schema.DirPredicate("valid")
+
+ testTempDir := t.TempDir()
+ jsonSchemaPath := filepath.Join(testutils.CurrentDir(t), "../../schema.json")
+
+ cases := []struct {
+ name string
+ file string
+ }{
+ {
+ name: "minimal valid file",
+ file: testdir("minimal-valid.yaml"),
+ },
+ {
+ name: "short mapping",
+ file: testdir("short-mapping.yaml"),
+ },
+ }
+
+ for _, testCase := range cases {
+ t.Run(testCase.name, func(t *testing.T) {
+ targetJSONFile := schema.TransformToJSON(t, testTempDir, testCase.file)
+
+ schemaLoader := gojsonschema.NewReferenceLoader("file://" + jsonSchemaPath)
+ documentLoader := gojsonschema.NewReferenceLoader("file://" + targetJSONFile)
+
+ result, err := gojsonschema.Validate(schemaLoader, documentLoader)
+ require.NoError(t, err)
+
+ assert.Empty(t, result.Errors(), "The document is not valid")
+ })
+ }
+}