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 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
|
package tests
import (
"encoding/json"
"fmt"
test "gopkg.in/check.v1"
"gopkg.in/rethinkdb/rethinkdb-go.v6/types"
)
type jsonChecker struct {
*test.CheckerInfo
}
func (j jsonChecker) Check(params []interface{}, names []string) (result bool, error string) {
var jsonParams []interface{}
for _, param := range params {
jsonParam, err := json.Marshal(param)
if err != nil {
return false, err.Error()
}
jsonParams = append(jsonParams, jsonParam)
}
return test.DeepEquals.Check(jsonParams, names)
}
// JsonEquals compares two interface{} objects by converting them to JSON and
// seeing if the strings match
var JsonEquals = &jsonChecker{
&test.CheckerInfo{Name: "JsonEquals", Params: []string{"obtained", "expected"}},
}
type geometryChecker struct {
*test.CheckerInfo
}
func (j geometryChecker) Check(params []interface{}, names []string) (result bool, error string) {
obtained, ok := params[0].(types.Geometry)
if !ok {
return false, "obtained must be a Geometry"
}
expectedType, ok := params[1].(string)
if !ok {
return false, "expectedType must be a string"
}
switch expectedType {
case "Polygon":
expectedCoords, ok := params[2].([][][]float64)
if !ok {
return false, "expectedCoords must be a [][][]float64"
}
return comparePolygon(expectedCoords, obtained)
case "LineString":
expectedCoords, ok := params[2].([][]float64)
if !ok {
return false, "expectedCoords must be a [][]float64"
}
return compareLineString(expectedCoords, obtained)
case "Point":
expectedCoords, ok := params[2].([]float64)
if !ok {
return false, "expectedCoords must be a []float64"
}
return comparePoint(expectedCoords, obtained)
default:
return false, "unknown expectedType"
}
}
// geometryEquals compares two geometry values, all coordinates are compared with a small amount of tolerance
var geometryEquals = &geometryChecker{
&test.CheckerInfo{Name: "geometryEquals", Params: []string{"obtained", "expectedType", "expectedCoords"}},
}
/* BEGIN FLOAT HELPERS */
// totally ripped off from math/all_test.go
// https://github.com/golang/go/blob/master/src/math/all_test.go#L1723-L1749
func tolerance(a, b, e float64) bool {
d := a - b
if d < 0 {
d = -d
}
if a != 0 {
e = e * a
if e < 0 {
e = -e
}
}
return d < e
}
func mehclose(a, b float64) bool { return tolerance(a, b, 1e-2) }
func kindaclose(a, b float64) bool { return tolerance(a, b, 1e-8) }
func prettyclose(a, b float64) bool { return tolerance(a, b, 1e-14) }
func veryclose(a, b float64) bool { return tolerance(a, b, 4e-16) }
func soclose(a, b, e float64) bool { return tolerance(a, b, e) }
func comparePolygon(expected [][][]float64, obtained types.Geometry) (result bool, error string) {
if obtained.Type != "Polygon" {
return false, fmt.Sprintf("obtained geometry has incorrect type, has %s but expected Polygon", obtained.Type)
}
for i, line := range obtained.Lines {
for j, point := range line {
ok, err := assertPointsEqual(
expected[i][j][0], point.Lon, // Lon
expected[i][j][1], point.Lat, // Lat
)
if !ok {
return false, err
}
}
}
return true, ""
}
func compareLineString(expected [][]float64, obtained types.Geometry) (result bool, error string) {
if obtained.Type != "LineString" {
return false, fmt.Sprintf("obtained geometry has incorrect type, has %s but expected LineString", obtained.Type)
}
for j, point := range obtained.Line {
ok, err := assertPointsEqual(
expected[j][0], point.Lon, // Lon
expected[j][1], point.Lat, // Lat
)
if !ok {
return false, err
}
}
return true, ""
}
func comparePoint(expected []float64, obtained types.Geometry) (result bool, error string) {
if obtained.Type != "Point" {
return false, fmt.Sprintf("obtained geometry has incorrect type, has %s but expected Point", obtained.Type)
}
return assertPointsEqual(
expected[0], obtained.Point.Lon, // Lon
expected[1], obtained.Point.Lat, // Lat
)
}
func assertPointsEqual(expectedLon, obtainedLon, expectedLat, obtainedLat float64) (result bool, error string) {
if !kindaclose(expectedLon, obtainedLon) {
return false, fmt.Sprintf("the deviation between the compared floats is too great [%v:%v]", expectedLon, obtainedLon)
}
if !kindaclose(expectedLat, obtainedLat) {
return false, fmt.Sprintf("the deviation between the compared floats is too great [%v:%v]", expectedLat, obtainedLat)
}
return true, ""
}
/* END FLOAT HELPERS */
|