File: failure.go

package info (click to toggle)
golang-github-viant-assertly 0.5.4-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 240 kB
  • sloc: makefile: 2
file content (134 lines) | stat: -rw-r--r-- 4,197 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package assertly

import (
	"fmt"
	"github.com/viant/toolbox"
	"strings"
	"unicode"
)

//Failure represents a validation failre
type Failure struct {
	Source   string
	Path     string
	Expected interface{}
	Actual   interface{}
	Args     []interface{}
	Reason   string
	Message  string
}

func (f *Failure) Index() int {
	pair := strings.SplitN(f.Path, ":", 2)
	if len(pair) != 2 {
		return -1
	}
	var index = ""
	var expectIndex = false
outer:
	for _, r := range pair[1] {

		switch r {
		case '[':
			expectIndex = true
		case ']':
			expectIndex = false
			if len(index) > 0 {
				break outer
			}
		default:
			if expectIndex && unicode.IsNumber(r) {
				index += string(r)
			}
		}
	}
	if len(index) == 0 {
		return -1
	}
	return toolbox.AsInt(index)
}

func (f *Failure) LeafKey() string {
	leafIndex := strings.LastIndex(f.Path, ".")
	if leafIndex == -1 {
		return ""
	}
	return string(f.Path[leafIndex+1:])
}

func removeDirectives(aMap map[string]interface{}) map[string]interface{} {
	var result = make(map[string]interface{})
	for k, v := range aMap {
		if strings.HasPrefix(k, "@") {
			continue
		}
		result[k] = v
	}
	return result
}

//NewFailure creates a new failure
func NewFailure(source, path string, reason string, expected, actual interface{}, args ...interface{}) *Failure {

	if expected != nil && toolbox.IsMap(expected) {
		expected = removeDirectives(toolbox.AsMap(expected))
	}
	if actual != nil && toolbox.IsMap(actual) {
		actual = removeDirectives(toolbox.AsMap(actual))
	}

	var result = &Failure{
		Source:   source,
		Path:     path,
		Reason:   reason,
		Expected: expected,
		Actual:   actual,
		Args:     args,
	}
	result.Message = FormatMessage(result)
	return result
}

func FormatMessage(failure *Failure) string {
	switch failure.Reason {
	case MissingEntryViolation:
		return fmt.Sprintf("entry for %v was missing, expected: %v, actual keys: %v", failure.Args[0], failure.Expected, failure.Actual)
	case MissingItemViolation:
		return fmt.Sprintf("item was missing, expected: %v, actual:  %v", failure.Expected, failure.Actual)
	case ItemMismatchViolation:
		return fmt.Sprintf("item was mismatched, key1: %v, key2: %v", failure.Expected, failure.Actual)
	case IncompatibleDataTypeViolation:
		return fmt.Sprintf("actual was %T, but expected %T(%v)", failure.Actual, failure.Expected, failure.Expected)
	case KeyExistsViolation:
		return fmt.Sprintf("key '%v' should exists", failure.Expected)
	case KeyDoesNotExistViolation:
		return fmt.Sprintf("'%v' should not exists", failure.Expected)
	case EqualViolation:
		return fmt.Sprintf("actual(%T): '%v' was not equal (%T) '%v'", failure.Actual, failure.Actual, failure.Expected, failure.Expected)
	case NotEqualViolation:
		return fmt.Sprintf("actual(%T): '%v' was equal (%T) '%v'", failure.Actual, failure.Actual, failure.Expected, failure.Expected)
	case LengthViolation:
		return fmt.Sprintf("actual length %v  was not equal: %v", failure.Actual, failure.Expected)
	case MissingCaseViolation:
		switchBy := failure.Args[0].([]string)
		caseValue := toolbox.AsString(failure.Args[1])
		var availableKeys = toolbox.MapKeysToStringSlice(failure.Expected)
		return fmt.Sprintf("actual case %v => %v, was missing in expected set: available keys: [%v]",
			strings.Join(switchBy, ","), caseValue, strings.Join(availableKeys, ","))
	case RegExprMatchesViolation:
		return fmt.Sprintf("actual: '%v' should matched %v", failure.Actual, failure.Expected)
	case RegExprDoesNotMatchViolation:
		return fmt.Sprintf("actual: '%v' should not be matched %v", failure.Actual, failure.Expected)
	case RangeViolation:
		return fmt.Sprintf("actual '%v' is not in: '%v'", failure.Actual, failure.Expected)
	case RangeNotViolation:
		return fmt.Sprintf("actual '%v' should not be in: '%v'", failure.Actual, failure.Expected)
	case ContainsViolation:
		return fmt.Sprintf("actual '%v' does not contain: '%v'", failure.Actual, failure.Expected)
	case DoesNotContainViolation:
		return fmt.Sprintf("actual '%v' should not not contain: '%v'", failure.Actual, failure.Expected)
	case PredicateViolation:
		return fmt.Sprintf("actual '%v' should pass predicate: '%v'", failure.Actual, failure.Expected)
	}
	return failure.Reason
}