Add ‘fncs’ package for all sql function commands
This commit is contained in:
parent
af00a45721
commit
08cf03f98b
42 changed files with 4119 additions and 0 deletions
237
util/fncs/args.go
Normal file
237
util/fncs/args.go
Normal file
|
@ -0,0 +1,237 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/abcum/surreal/sql"
|
||||
)
|
||||
|
||||
var defaultTime = time.Unix(0, 0)
|
||||
|
||||
func outputFloat(val float64) (interface{}, error) {
|
||||
switch {
|
||||
case math.IsNaN(val):
|
||||
return nil, nil
|
||||
case math.IsInf(val, 0):
|
||||
return nil, nil
|
||||
default:
|
||||
return val, nil
|
||||
}
|
||||
}
|
||||
|
||||
func ensureString(val interface{}) (out string, ok bool) {
|
||||
switch val := val.(type) {
|
||||
case string:
|
||||
return val, true
|
||||
case nil:
|
||||
return "", true
|
||||
default:
|
||||
return fmt.Sprint(val), true
|
||||
}
|
||||
}
|
||||
|
||||
func ensureBytes(val interface{}) (out []byte, ok bool) {
|
||||
switch val := val.(type) {
|
||||
case []byte:
|
||||
return val, true
|
||||
case string:
|
||||
return []byte(val), true
|
||||
case nil:
|
||||
return []byte(""), true
|
||||
default:
|
||||
return []byte(fmt.Sprint(val)), true
|
||||
}
|
||||
}
|
||||
|
||||
func ensureBool(val interface{}) (out bool, ok bool) {
|
||||
switch val := val.(type) {
|
||||
case bool:
|
||||
return val, true
|
||||
case string:
|
||||
if val, err := strconv.ParseBool(val); err == nil {
|
||||
return val, true
|
||||
}
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
|
||||
func ensureInt(val interface{}) (out int64, ok bool) {
|
||||
switch val := val.(type) {
|
||||
case int:
|
||||
return int64(val), true
|
||||
case int64:
|
||||
return int64(val), true
|
||||
case uint:
|
||||
return int64(val), true
|
||||
case uint64:
|
||||
return int64(val), true
|
||||
case float32:
|
||||
return int64(val), true
|
||||
case float64:
|
||||
return int64(val), true
|
||||
case string:
|
||||
if val, err := strconv.ParseFloat(val, 64); err == nil {
|
||||
return int64(val), true
|
||||
}
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func ensureFloat(val interface{}) (out float64, ok bool) {
|
||||
switch val := val.(type) {
|
||||
case int:
|
||||
return float64(val), true
|
||||
case int64:
|
||||
return float64(val), true
|
||||
case uint:
|
||||
return float64(val), true
|
||||
case uint64:
|
||||
return float64(val), true
|
||||
case float32:
|
||||
return float64(val), true
|
||||
case float64:
|
||||
return float64(val), true
|
||||
case string:
|
||||
if val, err := strconv.ParseFloat(val, 64); err == nil {
|
||||
return float64(val), true
|
||||
}
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func ensureTime(val interface{}) (out time.Time, ok bool) {
|
||||
switch val := val.(type) {
|
||||
case time.Time:
|
||||
return val, true
|
||||
}
|
||||
return defaultTime, false
|
||||
}
|
||||
|
||||
func ensurePoint(val interface{}) (out *sql.Point, ok bool) {
|
||||
switch val := val.(type) {
|
||||
case *sql.Point:
|
||||
return val, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func ensureCircle(val interface{}) (out *sql.Circle, ok bool) {
|
||||
switch val := val.(type) {
|
||||
case *sql.Circle:
|
||||
return val, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func ensurePolygon(val interface{}) (out *sql.Polygon, ok bool) {
|
||||
switch val := val.(type) {
|
||||
case *sql.Polygon:
|
||||
return val, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func ensureGeometry(val interface{}) (out sql.Expr, ok bool) {
|
||||
switch val := val.(type) {
|
||||
case *sql.Point:
|
||||
return val, true
|
||||
case *sql.Circle:
|
||||
return val, true
|
||||
case *sql.Polygon:
|
||||
return val, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func ensureDuration(val interface{}) (out time.Duration, ok bool) {
|
||||
switch val := val.(type) {
|
||||
case time.Duration:
|
||||
return val, true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func ensureSlice(args interface{}) (out []interface{}, ok bool) {
|
||||
if i, ok := args.([]interface{}); ok {
|
||||
out = i
|
||||
} else {
|
||||
out = []interface{}{args}
|
||||
}
|
||||
return out, true
|
||||
}
|
||||
|
||||
func ensureObject(args interface{}) (out map[string]interface{}, ok bool) {
|
||||
if i, ok := args.(map[string]interface{}); ok {
|
||||
out = i
|
||||
} else {
|
||||
out = map[string]interface{}{}
|
||||
}
|
||||
return out, true
|
||||
}
|
||||
|
||||
func ensureInts(args interface{}) (out []int64) {
|
||||
arr, _ := ensureSlice(args)
|
||||
for _, val := range arr {
|
||||
switch val := val.(type) {
|
||||
case int:
|
||||
out = append(out, int64(val))
|
||||
case int64:
|
||||
out = append(out, int64(val))
|
||||
case uint:
|
||||
out = append(out, int64(val))
|
||||
case uint64:
|
||||
out = append(out, int64(val))
|
||||
case float32:
|
||||
out = append(out, int64(val))
|
||||
case float64:
|
||||
out = append(out, int64(val))
|
||||
case string:
|
||||
if val, err := strconv.ParseFloat(val, 64); err == nil {
|
||||
out = append(out, int64(val))
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func ensureFloats(args interface{}) (out []float64) {
|
||||
arr, _ := ensureSlice(args)
|
||||
for _, val := range arr {
|
||||
switch val := val.(type) {
|
||||
case int:
|
||||
out = append(out, float64(val))
|
||||
case int64:
|
||||
out = append(out, float64(val))
|
||||
case uint:
|
||||
out = append(out, float64(val))
|
||||
case uint64:
|
||||
out = append(out, float64(val))
|
||||
case float32:
|
||||
out = append(out, float64(val))
|
||||
case float64:
|
||||
out = append(out, float64(val))
|
||||
case string:
|
||||
if val, err := strconv.ParseFloat(val, 64); err == nil {
|
||||
out = append(out, float64(val))
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
167
util/fncs/args_test.go
Normal file
167
util/fncs/args_test.go
Normal file
|
@ -0,0 +1,167 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/abcum/surreal/sql"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestArgs(t *testing.T) {
|
||||
|
||||
now := time.Now()
|
||||
|
||||
args := []interface{}{
|
||||
int(1),
|
||||
int64(1),
|
||||
uint(1),
|
||||
uint64(1),
|
||||
float32(1.5),
|
||||
float64(1.5),
|
||||
string("1"),
|
||||
string("1.5"),
|
||||
string("test"),
|
||||
[]byte("test"),
|
||||
map[string]interface{}{"test": true},
|
||||
}
|
||||
|
||||
good := args[0:8]
|
||||
|
||||
oops := args[8:11]
|
||||
|
||||
Convey("An argument will convert to string if possible", t, func() {
|
||||
for _, arg := range args {
|
||||
val, ok := ensureString(arg)
|
||||
So(ok, ShouldEqual, true)
|
||||
So(val, ShouldHaveSameTypeAs, string(""))
|
||||
}
|
||||
})
|
||||
|
||||
Convey("An argument will convert to []byte if possible", t, func() {
|
||||
for _, arg := range args {
|
||||
val, ok := ensureBytes(arg)
|
||||
So(ok, ShouldEqual, true)
|
||||
So(val, ShouldHaveSameTypeAs, []byte(""))
|
||||
}
|
||||
})
|
||||
|
||||
Convey("An argument will convert to int64 if possible", t, func() {
|
||||
for _, arg := range good {
|
||||
val, ok := ensureInt(arg)
|
||||
So(ok, ShouldEqual, true)
|
||||
So(val, ShouldHaveSameTypeAs, int64(0))
|
||||
}
|
||||
for _, arg := range oops {
|
||||
val, ok := ensureInt(arg)
|
||||
So(ok, ShouldEqual, false)
|
||||
So(val, ShouldHaveSameTypeAs, int64(0))
|
||||
}
|
||||
})
|
||||
|
||||
Convey("An argument will convert to float64 if possible", t, func() {
|
||||
for _, arg := range good {
|
||||
val, ok := ensureFloat(arg)
|
||||
So(ok, ShouldEqual, true)
|
||||
So(val, ShouldHaveSameTypeAs, float64(0))
|
||||
}
|
||||
for _, arg := range oops {
|
||||
val, ok := ensureFloat(arg)
|
||||
So(ok, ShouldEqual, false)
|
||||
So(val, ShouldHaveSameTypeAs, float64(0))
|
||||
}
|
||||
})
|
||||
|
||||
Convey("An argument will convert to time.Time if possible", t, func() {
|
||||
res, ok := ensureTime("test")
|
||||
So(ok, ShouldEqual, false)
|
||||
So(res, ShouldEqual, time.Unix(0, 0))
|
||||
one, ok := ensureTime(now)
|
||||
So(ok, ShouldEqual, true)
|
||||
So(one, ShouldEqual, now)
|
||||
})
|
||||
|
||||
Convey("An argument will convert to *sql.Point if possible", t, func() {
|
||||
res, ok := ensurePoint("test")
|
||||
So(ok, ShouldEqual, false)
|
||||
So(res, ShouldEqual, nil)
|
||||
one, ok := ensurePoint(&sql.Point{})
|
||||
So(ok, ShouldEqual, true)
|
||||
So(one, ShouldResemble, &sql.Point{})
|
||||
})
|
||||
|
||||
Convey("An argument will convert to *sql.Circle if possible", t, func() {
|
||||
res, ok := ensureCircle("test")
|
||||
So(ok, ShouldEqual, false)
|
||||
So(res, ShouldEqual, nil)
|
||||
one, ok := ensureCircle(&sql.Circle{})
|
||||
So(ok, ShouldEqual, true)
|
||||
So(one, ShouldResemble, &sql.Circle{})
|
||||
})
|
||||
|
||||
Convey("An argument will convert to *sql.Polygon if possible", t, func() {
|
||||
res, ok := ensurePolygon("test")
|
||||
So(ok, ShouldEqual, false)
|
||||
So(res, ShouldEqual, nil)
|
||||
one, ok := ensurePolygon(&sql.Polygon{})
|
||||
So(ok, ShouldEqual, true)
|
||||
So(one, ShouldResemble, &sql.Polygon{})
|
||||
})
|
||||
|
||||
Convey("An argument will convert to *sql.Polygon if possible", t, func() {
|
||||
res, ok := ensureGeometry("test")
|
||||
So(ok, ShouldEqual, false)
|
||||
So(res, ShouldEqual, nil)
|
||||
one, ok := ensureGeometry(&sql.Point{})
|
||||
So(ok, ShouldEqual, true)
|
||||
So(one, ShouldResemble, &sql.Point{})
|
||||
two, ok := ensureGeometry(&sql.Circle{})
|
||||
So(ok, ShouldEqual, true)
|
||||
So(two, ShouldResemble, &sql.Circle{})
|
||||
tre, ok := ensureGeometry(&sql.Polygon{})
|
||||
So(ok, ShouldEqual, true)
|
||||
So(tre, ShouldResemble, &sql.Polygon{})
|
||||
})
|
||||
|
||||
Convey("Arguments are converted to []int64 if possible", t, func() {
|
||||
res := ensureInts(args)
|
||||
So(res, ShouldHaveSameTypeAs, []int64{})
|
||||
So(len(res), ShouldEqual, 8)
|
||||
})
|
||||
|
||||
Convey("Arguments are converted to []float64 if possible", t, func() {
|
||||
res := ensureFloats(args)
|
||||
So(res, ShouldHaveSameTypeAs, []float64{})
|
||||
So(len(res), ShouldEqual, 8)
|
||||
})
|
||||
|
||||
Convey("Arguments are converted to []interface{} if possible", t, func() {
|
||||
for _, arg := range args {
|
||||
res, _ := ensureSlice(arg)
|
||||
So(res, ShouldHaveSameTypeAs, []interface{}{})
|
||||
}
|
||||
})
|
||||
|
||||
Convey("Arguments are converted to map[string]interface{} if possible", t, func() {
|
||||
for _, arg := range args {
|
||||
res, _ := ensureObject(arg)
|
||||
So(res, ShouldHaveSameTypeAs, map[string]interface{}{})
|
||||
}
|
||||
})
|
||||
|
||||
}
|
27
util/fncs/batch.go
Normal file
27
util/fncs/batch.go
Normal file
|
@ -0,0 +1,27 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/abcum/surreal/sql"
|
||||
)
|
||||
|
||||
func batch(ctx context.Context, args ...interface{}) (*sql.Batch, error) {
|
||||
tb, _ := ensureString(args[0])
|
||||
id, _ := ensureSlice(args[1])
|
||||
return sql.NewBatch(tb, id), nil
|
||||
}
|
36
util/fncs/batch_test.go
Normal file
36
util/fncs/batch_test.go
Normal file
|
@ -0,0 +1,36 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/abcum/surreal/sql"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestBatch(t *testing.T) {
|
||||
|
||||
var res interface{}
|
||||
|
||||
Convey("batch() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "batch", 1, []interface{}{1, 2, 3})
|
||||
So(res, ShouldResemble, sql.NewBatch("1", []interface{}{1, 2, 3}))
|
||||
res, _ = Run(context.Background(), "batch", "test", []interface{}{1, 2, 3})
|
||||
So(res, ShouldResemble, sql.NewBatch("test", []interface{}{1, 2, 3}))
|
||||
})
|
||||
|
||||
}
|
40
util/fncs/bcrypt.go
Normal file
40
util/fncs/bcrypt.go
Normal file
|
@ -0,0 +1,40 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
func bcryptCompare(ctx context.Context, args ...interface{}) (bool, error) {
|
||||
if h, ok := ensureString(args[0]); ok {
|
||||
if s, ok := ensureString(args[1]); ok {
|
||||
e := bcrypt.CompareHashAndPassword([]byte(h), []byte(s))
|
||||
if e == nil {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func bcryptGenerate(ctx context.Context, args ...interface{}) ([]byte, error) {
|
||||
s, _ := ensureString(args[0])
|
||||
p := []byte(s)
|
||||
o := bcrypt.DefaultCost
|
||||
return bcrypt.GenerateFromPassword(p, o)
|
||||
}
|
41
util/fncs/bcrypt_test.go
Normal file
41
util/fncs/bcrypt_test.go
Normal file
|
@ -0,0 +1,41 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestBcrypt(t *testing.T) {
|
||||
|
||||
Convey("bcrypt.compare(a, b) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "bcrypt.compare", "$2y$10$XPMT7nWucHJK113jjomfJ.xa64/jhH7sYrRJ9/0Q2CjzBTGwejUx.", "test")
|
||||
So(res, ShouldEqual, true)
|
||||
})
|
||||
|
||||
Convey("bcrypt.compare(a, b) errors properly", t, func() {
|
||||
res, _ := Run(context.Background(), "bcrypt.compare", "$2y$10$XPMT7nWucHJK113jjomfJ.xa64/jhH7sYrRJ9/0Q2CjzBTGwejUx.", "wrong")
|
||||
So(res, ShouldEqual, false)
|
||||
})
|
||||
|
||||
Convey("bcrypt.generate(a) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "bcrypt.generate", "test")
|
||||
So(res, ShouldHaveSameTypeAs, []byte("test"))
|
||||
})
|
||||
|
||||
}
|
49
util/fncs/count.go
Normal file
49
util/fncs/count.go
Normal file
|
@ -0,0 +1,49 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
func count(ctx context.Context, args ...interface{}) (out float64, err error) {
|
||||
arr, _ := ensureSlice(args[0])
|
||||
for _, v := range arr {
|
||||
if v != nil {
|
||||
out++
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func countIf(ctx context.Context, args ...interface{}) (out float64, err error) {
|
||||
arr, _ := ensureSlice(args[0])
|
||||
for _, v := range arr {
|
||||
if v == args[1] {
|
||||
out++
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func countNot(ctx context.Context, args ...interface{}) (out float64, err error) {
|
||||
arr, _ := ensureSlice(args[0])
|
||||
for _, v := range arr {
|
||||
if v != args[1] {
|
||||
out++
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
57
util/fncs/count_test.go
Normal file
57
util/fncs/count_test.go
Normal file
|
@ -0,0 +1,57 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestCount(t *testing.T) {
|
||||
|
||||
var res interface{}
|
||||
|
||||
var test = []interface{}{int(1), int(2), nil, float64(3.5), float64(4.5), float64(3.5)}
|
||||
|
||||
Convey("count() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "count", "test")
|
||||
So(res, ShouldEqual, 1)
|
||||
res, _ = Run(context.Background(), "count", 10)
|
||||
So(res, ShouldEqual, 1)
|
||||
res, _ = Run(context.Background(), "count", test)
|
||||
So(res, ShouldEqual, 5)
|
||||
})
|
||||
|
||||
Convey("count.if() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "count.if", "test", 3.5)
|
||||
So(res, ShouldEqual, 0)
|
||||
res, _ = Run(context.Background(), "count.if", 10, 3.5)
|
||||
So(res, ShouldEqual, 0)
|
||||
res, _ = Run(context.Background(), "count.if", test, 3.5)
|
||||
So(res, ShouldEqual, 2)
|
||||
})
|
||||
|
||||
Convey("count.not() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "count.not", "test", 3.5)
|
||||
So(res, ShouldEqual, 1)
|
||||
res, _ = Run(context.Background(), "count.not", 10, 3.5)
|
||||
So(res, ShouldEqual, 1)
|
||||
res, _ = Run(context.Background(), "count.not", test, 3.5)
|
||||
So(res, ShouldEqual, 4)
|
||||
})
|
||||
|
||||
}
|
43
util/fncs/email.go
Normal file
43
util/fncs/email.go
Normal file
|
@ -0,0 +1,43 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/asaskevich/govalidator"
|
||||
)
|
||||
|
||||
func emailUser(ctx context.Context, args ...interface{}) (string, error) {
|
||||
v, _ := ensureString(args[0])
|
||||
if p := strings.LastIndexByte(v, '@'); p > 0 {
|
||||
return v[:p], nil
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func emailDomain(ctx context.Context, args ...interface{}) (string, error) {
|
||||
v, _ := ensureString(args[0])
|
||||
if p := strings.LastIndexByte(v, '@'); p > 0 {
|
||||
return v[p+1:], nil
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func emailValid(ctx context.Context, args ...interface{}) (bool, error) {
|
||||
v, _ := ensureString(args[0])
|
||||
return govalidator.IsEmail(v), nil
|
||||
}
|
60
util/fncs/email_test.go
Normal file
60
util/fncs/email_test.go
Normal file
|
@ -0,0 +1,60 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestEmail(t *testing.T) {
|
||||
|
||||
Convey("email.user(a) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "email.user", "tobie@abcum.com")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
So(res, ShouldEqual, "tobie")
|
||||
})
|
||||
|
||||
Convey("email.user(a) errors properly", t, func() {
|
||||
res, _ := Run(context.Background(), "email.user", "test")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
So(res, ShouldEqual, "")
|
||||
})
|
||||
|
||||
Convey("email.domain(a) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "email.domain", "tobie@abcum.com")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
So(res, ShouldEqual, "abcum.com")
|
||||
})
|
||||
|
||||
Convey("email.domain(a) errors properly", t, func() {
|
||||
res, _ := Run(context.Background(), "email.domain", "test")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
So(res, ShouldEqual, "")
|
||||
})
|
||||
|
||||
Convey("email.valid(a) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "email.valid", "tobie@abcum.com")
|
||||
So(res, ShouldEqual, true)
|
||||
})
|
||||
|
||||
Convey("email.valid(a) errors properly", t, func() {
|
||||
res, _ := Run(context.Background(), "email.valid", "test")
|
||||
So(res, ShouldEqual, false)
|
||||
})
|
||||
|
||||
}
|
325
util/fncs/fnc.go
Normal file
325
util/fncs/fnc.go
Normal file
|
@ -0,0 +1,325 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import "context"
|
||||
|
||||
func Run(ctx context.Context, name string, args ...interface{}) (interface{}, error) {
|
||||
|
||||
switch name {
|
||||
|
||||
case "batch":
|
||||
return batch(ctx, args...)
|
||||
case "difference":
|
||||
return difference(ctx, args...)
|
||||
case "distinct":
|
||||
return distinct(ctx, args...)
|
||||
case "get":
|
||||
return get(ctx, args...)
|
||||
case "if":
|
||||
return ifel(ctx, args...)
|
||||
case "intersect":
|
||||
return intersect(ctx, args...)
|
||||
case "model":
|
||||
return model(ctx, args...)
|
||||
case "table":
|
||||
return table(ctx, args...)
|
||||
case "thing":
|
||||
return thing(ctx, args...)
|
||||
case "union":
|
||||
return union(ctx, args...)
|
||||
|
||||
// Count implementation
|
||||
case "count":
|
||||
return count(ctx, args...)
|
||||
case "count.if":
|
||||
return countIf(ctx, args...)
|
||||
case "count.not":
|
||||
return countNot(ctx, args...)
|
||||
|
||||
// Json implementation
|
||||
case "json.decode":
|
||||
return jsonDecode(ctx, args...)
|
||||
case "json.encode":
|
||||
return jsonEncode(ctx, args...)
|
||||
|
||||
// Geo implementation
|
||||
case "geo.point":
|
||||
return geoPoint(ctx, args...)
|
||||
case "geo.circle":
|
||||
return geoCircle(ctx, args...)
|
||||
case "geo.polygon":
|
||||
return geoPolygon(ctx, args...)
|
||||
case "geo.distance":
|
||||
return geoDistance(ctx, args...)
|
||||
case "geo.inside":
|
||||
return geoInside(ctx, args...)
|
||||
case "geo.intersects":
|
||||
return geoIntersects(ctx, args...)
|
||||
case "geo.hash.decode":
|
||||
return geoHashDecode(ctx, args...)
|
||||
case "geo.hash.encode":
|
||||
return geoHashEncode(ctx, args...)
|
||||
|
||||
// Http implementation
|
||||
case "http.head":
|
||||
return httpHead(ctx, args...)
|
||||
case "http.get":
|
||||
return httpGet(ctx, args...)
|
||||
case "http.put":
|
||||
return httpPut(ctx, args...)
|
||||
case "http.post":
|
||||
return httpPost(ctx, args...)
|
||||
case "http.patch":
|
||||
return httpPatch(ctx, args...)
|
||||
case "http.delete":
|
||||
return httpDelete(ctx, args...)
|
||||
case "http.async.head":
|
||||
return httpAsyncHead(ctx, args...)
|
||||
case "http.async.get":
|
||||
return httpAsyncGet(ctx, args...)
|
||||
case "http.async.put":
|
||||
return httpAsyncPut(ctx, args...)
|
||||
case "http.async.post":
|
||||
return httpAsyncPost(ctx, args...)
|
||||
case "http.async.patch":
|
||||
return httpAsyncPatch(ctx, args...)
|
||||
case "http.async.delete":
|
||||
return httpAsyncDelete(ctx, args...)
|
||||
|
||||
// Math implementation
|
||||
case "math.abs", "abs":
|
||||
return mathAbs(ctx, args...)
|
||||
case "math.bottom", "bottom":
|
||||
return mathBottom(ctx, args...)
|
||||
case "math.ceil", "ceil":
|
||||
return mathCeil(ctx, args...)
|
||||
case "math.correlation", "correlation":
|
||||
return mathCorrelation(ctx, args...)
|
||||
case "math.covariance", "covariance":
|
||||
return mathCovariance(ctx, args...)
|
||||
case "math.floor", "floor":
|
||||
return mathFloor(ctx, args...)
|
||||
case "math.geometricmean", "geometricmean":
|
||||
return mathGeometricmean(ctx, args...)
|
||||
case "math.harmonicmean", "harmonicmean":
|
||||
return mathHarmonicmean(ctx, args...)
|
||||
case "math.interquartile", "interquartile":
|
||||
return mathInterquartile(ctx, args...)
|
||||
case "math.max", "max":
|
||||
return mathMax(ctx, args...)
|
||||
case "math.mean", "mean":
|
||||
return mathMean(ctx, args...)
|
||||
case "math.median", "median":
|
||||
return mathMedian(ctx, args...)
|
||||
case "math.midhinge", "midhinge":
|
||||
return mathMidhinge(ctx, args...)
|
||||
case "math.min", "min":
|
||||
return mathMin(ctx, args...)
|
||||
case "math.mode", "mode":
|
||||
return mathMode(ctx, args...)
|
||||
case "math.percentile", "percentile":
|
||||
return mathPercentile(ctx, args...)
|
||||
case "math.round", "round":
|
||||
return mathRound(ctx, args...)
|
||||
case "math.sample", "sample":
|
||||
return mathSample(ctx, args...)
|
||||
case "math.spread", "spread":
|
||||
return mathSpread(ctx, args...)
|
||||
case "math.stddev", "stddev":
|
||||
return mathStddev(ctx, args...)
|
||||
case "math.sum", "sum":
|
||||
return mathSum(ctx, args...)
|
||||
case "math.top", "top":
|
||||
return mathTop(ctx, args...)
|
||||
case "math.trimean", "trimean":
|
||||
return mathTrimean(ctx, args...)
|
||||
case "math.variance", "variance":
|
||||
return mathVariance(ctx, args...)
|
||||
|
||||
// String implementation
|
||||
case "string.concat":
|
||||
return stringConcat(ctx, args...)
|
||||
case "string.contains":
|
||||
return stringContains(ctx, args...)
|
||||
case "string.endsWith":
|
||||
return stringEndsWith(ctx, args...)
|
||||
case "string.format":
|
||||
return stringFormat(ctx, args...)
|
||||
case "string.includes":
|
||||
return stringIncludes(ctx, args...)
|
||||
case "string.join":
|
||||
return stringJoin(ctx, args...)
|
||||
case "string.length":
|
||||
return stringLength(ctx, args...)
|
||||
case "string.levenshtein":
|
||||
return stringLevenshtein(ctx, args...)
|
||||
case "string.lowercase":
|
||||
return stringLowercase(ctx, args...)
|
||||
case "string.repeat":
|
||||
return stringRepeat(ctx, args...)
|
||||
case "string.replace":
|
||||
return stringReplace(ctx, args...)
|
||||
case "string.reverse":
|
||||
return stringReverse(ctx, args...)
|
||||
case "string.search":
|
||||
return stringSearch(ctx, args...)
|
||||
case "string.slice":
|
||||
return stringSlice(ctx, args...)
|
||||
case "string.split":
|
||||
return stringSplit(ctx, args...)
|
||||
case "string.startsWith":
|
||||
return stringStartsWith(ctx, args...)
|
||||
case "string.substr":
|
||||
return stringSubstr(ctx, args...)
|
||||
case "string.trim":
|
||||
return stringTrim(ctx, args...)
|
||||
case "string.uppercase":
|
||||
return stringUppercase(ctx, args...)
|
||||
case "string.words":
|
||||
return stringWords(ctx, args...)
|
||||
|
||||
// Hash implementation
|
||||
case "hash.md5":
|
||||
return hashMd5(ctx, args...)
|
||||
case "hash.sha1":
|
||||
return hashSha1(ctx, args...)
|
||||
case "hash.sha256":
|
||||
return hashSha256(ctx, args...)
|
||||
case "hash.sha512":
|
||||
return hashSha512(ctx, args...)
|
||||
|
||||
// Time implementation
|
||||
case "time.now":
|
||||
return timeNow(ctx, args...)
|
||||
case "time.add":
|
||||
return timeAdd(ctx, args...)
|
||||
case "time.age":
|
||||
return timeAge(ctx, args...)
|
||||
case "time.floor":
|
||||
return timeFloor(ctx, args...)
|
||||
case "time.round":
|
||||
return timeRound(ctx, args...)
|
||||
case "time.day":
|
||||
return timeDay(ctx, args...)
|
||||
case "time.hour":
|
||||
return timeHour(ctx, args...)
|
||||
case "time.mins":
|
||||
return timeMins(ctx, args...)
|
||||
case "time.month":
|
||||
return timeMonth(ctx, args...)
|
||||
case "time.nano":
|
||||
return timeNano(ctx, args...)
|
||||
case "time.secs":
|
||||
return timeSecs(ctx, args...)
|
||||
case "time.unix":
|
||||
return timeUnix(ctx, args...)
|
||||
case "time.year":
|
||||
return timeYear(ctx, args...)
|
||||
|
||||
// Email implementation
|
||||
case "email.user":
|
||||
return emailUser(ctx, args...)
|
||||
case "email.domain":
|
||||
return emailDomain(ctx, args...)
|
||||
case "email.valid":
|
||||
return emailValid(ctx, args...)
|
||||
|
||||
// Bcrypt implementation
|
||||
case "bcrypt.compare":
|
||||
return bcryptCompare(ctx, args...)
|
||||
case "bcrypt.generate":
|
||||
return bcryptGenerate(ctx, args...)
|
||||
|
||||
// Scrypt implementation
|
||||
case "scrypt.compare":
|
||||
return scryptCompare(ctx, args...)
|
||||
case "scrypt.generate":
|
||||
return scryptGenerate(ctx, args...)
|
||||
|
||||
// Rand implementation
|
||||
case "rand":
|
||||
return rand(ctx, args...)
|
||||
case "uuid":
|
||||
return randUuid(ctx, args...)
|
||||
case "rand.bool":
|
||||
return randBool(ctx, args...)
|
||||
case "rand.uuid":
|
||||
return randUuid(ctx, args...)
|
||||
case "rand.enum":
|
||||
return randEnum(ctx, args...)
|
||||
case "rand.time":
|
||||
return randTime(ctx, args...)
|
||||
case "rand.string":
|
||||
return randString(ctx, args...)
|
||||
case "rand.integer":
|
||||
return randInteger(ctx, args...)
|
||||
case "rand.decimal":
|
||||
return randDecimal(ctx, args...)
|
||||
case "rand.word":
|
||||
return randWord(ctx, args...)
|
||||
case "rand.sentence":
|
||||
return randSentence(ctx, args...)
|
||||
case "rand.paragraph":
|
||||
return randParagraph(ctx, args...)
|
||||
case "rand.person.email":
|
||||
return randPersonEmail(ctx, args...)
|
||||
case "rand.person.phone":
|
||||
return randPersonPhone(ctx, args...)
|
||||
case "rand.person.fullname":
|
||||
return randPersonFullname(ctx, args...)
|
||||
case "rand.person.firstname":
|
||||
return randPersonFirstname(ctx, args...)
|
||||
case "rand.person.lastname":
|
||||
return randPersonLastname(ctx, args...)
|
||||
case "rand.person.username":
|
||||
return randPersonUsername(ctx, args...)
|
||||
case "rand.person.jobtitle":
|
||||
return randPersonJobtitle(ctx, args...)
|
||||
case "rand.company.name":
|
||||
return randCompanyName(ctx, args...)
|
||||
case "rand.company.industry":
|
||||
return randCompanyIndustry(ctx, args...)
|
||||
case "rand.location.name":
|
||||
return randLocationName(ctx, args...)
|
||||
case "rand.location.address":
|
||||
return randLocationAddress(ctx, args...)
|
||||
case "rand.location.street":
|
||||
return randLocationStreet(ctx, args...)
|
||||
case "rand.location.city":
|
||||
return randLocationCity(ctx, args...)
|
||||
case "rand.location.state":
|
||||
return randLocationState(ctx, args...)
|
||||
case "rand.location.county":
|
||||
return randLocationCounty(ctx, args...)
|
||||
case "rand.location.zipcode":
|
||||
return randLocationZipcode(ctx, args...)
|
||||
case "rand.location.postcode":
|
||||
return randLocationPostcode(ctx, args...)
|
||||
case "rand.location.country":
|
||||
return randLocationCountry(ctx, args...)
|
||||
case "rand.location.altitude":
|
||||
return randLocationAltitude(ctx, args...)
|
||||
case "rand.location.latitude":
|
||||
return randLocationLatitude(ctx, args...)
|
||||
case "rand.location.longitude":
|
||||
return randLocationLongitude(ctx, args...)
|
||||
|
||||
default:
|
||||
return nil, nil // Should never get here
|
||||
|
||||
}
|
||||
|
||||
}
|
32
util/fncs/fnc_test.go
Normal file
32
util/fncs/fnc_test.go
Normal file
|
@ -0,0 +1,32 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestNil(t *testing.T) {
|
||||
|
||||
Convey("invalid.function() returns nil", t, func() {
|
||||
res, _ := Run(context.Background(), "invalid.function")
|
||||
So(res, ShouldHaveSameTypeAs, nil)
|
||||
So(res, ShouldEqual, nil)
|
||||
})
|
||||
|
||||
}
|
115
util/fncs/geo.go
Normal file
115
util/fncs/geo.go
Normal file
|
@ -0,0 +1,115 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/abcum/surreal/sql"
|
||||
"github.com/abcum/surreal/util/geof"
|
||||
)
|
||||
|
||||
func geoPoint(ctx context.Context, args ...interface{}) (*sql.Point, error) {
|
||||
switch len(args) {
|
||||
case 1:
|
||||
if p, ok := ensurePoint(args[0]); ok {
|
||||
return p, nil
|
||||
}
|
||||
if p := ensureFloats(args[0]); len(p) == 2 {
|
||||
return sql.NewPoint(p[0], p[1]), nil
|
||||
}
|
||||
case 2:
|
||||
if lat, ok := ensureFloat(args[0]); ok {
|
||||
if lng, ok := ensureFloat(args[1]); ok {
|
||||
return sql.NewPoint(lat, lng), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func geoCircle(ctx context.Context, args ...interface{}) (*sql.Circle, error) {
|
||||
if cen, ok := ensurePoint(args[0]); ok {
|
||||
if rad, ok := ensureFloat(args[1]); ok {
|
||||
return sql.NewCircle(cen, rad), nil
|
||||
}
|
||||
}
|
||||
if val := ensureFloats(args[0]); len(val) == 2 {
|
||||
cen, _ := geoPoint(ctx, val[0], val[1])
|
||||
if rad, ok := ensureFloat(args[1]); ok {
|
||||
return sql.NewCircle(cen, rad), nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func geoPolygon(ctx context.Context, args ...interface{}) (*sql.Polygon, error) {
|
||||
switch len(args) {
|
||||
case 0, 1, 2:
|
||||
// Not enough arguments, so just ignore
|
||||
default:
|
||||
var pnts sql.Points
|
||||
for _, a := range args {
|
||||
if p, _ := geoPoint(ctx, a); p != nil {
|
||||
pnts = append(pnts, p)
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
return sql.NewPolygon(pnts...), nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func geoDistance(ctx context.Context, args ...interface{}) (float64, error) {
|
||||
if pnt, ok := ensurePoint(args[0]); ok {
|
||||
if frm, ok := ensurePoint(args[1]); ok {
|
||||
return geof.Haversine(pnt, frm), nil
|
||||
}
|
||||
}
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
func geoInside(ctx context.Context, args ...interface{}) (bool, error) {
|
||||
if a, ok := ensureGeometry(args[0]); ok {
|
||||
if b, ok := ensureGeometry(args[1]); ok {
|
||||
return geof.Inside(a, b), nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func geoIntersects(ctx context.Context, args ...interface{}) (bool, error) {
|
||||
if a, ok := ensureGeometry(args[0]); ok {
|
||||
if b, ok := ensureGeometry(args[1]); ok {
|
||||
return geof.Intersects(a, b), nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func geoHashDecode(ctx context.Context, args ...interface{}) (*sql.Point, error) {
|
||||
s, _ := ensureString(args[0])
|
||||
return geof.GeohashDecode(s), nil
|
||||
}
|
||||
|
||||
func geoHashEncode(ctx context.Context, args ...interface{}) (string, error) {
|
||||
if pnt, ok := ensurePoint(args[0]); ok {
|
||||
if acc, ok := ensureInt(args[1]); ok {
|
||||
return geof.GeohashEncode(pnt, acc), nil
|
||||
}
|
||||
}
|
||||
return "", nil
|
||||
}
|
90
util/fncs/geo_test.go
Normal file
90
util/fncs/geo_test.go
Normal file
|
@ -0,0 +1,90 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/abcum/surreal/sql"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestGeo(t *testing.T) {
|
||||
|
||||
var res interface{}
|
||||
|
||||
Convey("geo.point(a, b) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "geo.point", "test", "test")
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "geo.point", &sql.Point{38.898556, -77.037852})
|
||||
So(res, ShouldResemble, &sql.Point{38.898556, -77.037852})
|
||||
res, _ = Run(context.Background(), "geo.point", []interface{}{38.898556, -77.037852})
|
||||
So(res, ShouldResemble, &sql.Point{38.898556, -77.037852})
|
||||
res, _ = Run(context.Background(), "geo.point", 38.898556, -77.037852)
|
||||
So(res, ShouldResemble, &sql.Point{38.898556, -77.037852})
|
||||
})
|
||||
|
||||
Convey("geo.circle(a, b) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "geo.circle", "test", "test")
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "geo.circle", &sql.Point{38.898556, -77.037852}, 100)
|
||||
So(res, ShouldResemble, &sql.Circle{&sql.Point{38.898556, -77.037852}, 100})
|
||||
res, _ = Run(context.Background(), "geo.circle", []interface{}{38.898556, -77.037852}, 100)
|
||||
So(res, ShouldResemble, &sql.Circle{&sql.Point{38.898556, -77.037852}, 100})
|
||||
})
|
||||
|
||||
Convey("geo.polygon(a, b) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "geo.polygon", "test")
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "geo.polygon", "test", "test", "test")
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "geo.polygon", "test", &sql.Point{}, &sql.Point{}, &sql.Point{})
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "geo.polygon", &sql.Point{}, &sql.Point{}, &sql.Point{}, &sql.Point{})
|
||||
So(res, ShouldResemble, &sql.Polygon{sql.Points{&sql.Point{}, &sql.Point{}, &sql.Point{}, &sql.Point{}}})
|
||||
})
|
||||
|
||||
Convey("geo.distance(a, b, c, d) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "geo.distance", &sql.Point{38.898556, -77.037852}, &sql.Point{38.897147, -77.043934})
|
||||
So(res, ShouldEqual, 549.1557912048178)
|
||||
})
|
||||
|
||||
Convey("geo.distance(a, b, c, d) errors properly", t, func() {
|
||||
res, _ = Run(context.Background(), "geo.distance", &sql.Point{38.898556, -77.037852}, "null")
|
||||
So(res, ShouldEqual, -1)
|
||||
})
|
||||
|
||||
Convey("geo.hash.decode(a) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "geo.hash.decode", "dqcjq")
|
||||
So(res, ShouldResemble, &sql.Point{38.91357421875, -77.05810546875})
|
||||
res, _ = Run(context.Background(), "geo.hash.decode", "dqcjqcq8x")
|
||||
So(res, ShouldResemble, &sql.Point{38.9230709412368, -77.06750950572314})
|
||||
})
|
||||
|
||||
Convey("geo.hash.encode(a, b, c) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "geo.hash.encode", &sql.Point{38.898556, -77.037852}, 5)
|
||||
So(res, ShouldEqual, "dqcjq")
|
||||
res, _ = Run(context.Background(), "geo.hash.encode", &sql.Point{38.898556, -77.037852}, 9)
|
||||
So(res, ShouldEqual, "dqcjqcq8x")
|
||||
})
|
||||
|
||||
Convey("geo.hash.encode(a, b, c) errors properly", t, func() {
|
||||
res, _ = Run(context.Background(), "geo.hash.encode", 0, 0, "null")
|
||||
So(res, ShouldEqual, "")
|
||||
})
|
||||
|
||||
}
|
33
util/fncs/get.go
Normal file
33
util/fncs/get.go
Normal file
|
@ -0,0 +1,33 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/abcum/surreal/sql"
|
||||
"github.com/abcum/surreal/util/data"
|
||||
)
|
||||
|
||||
func get(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
doc := data.Consume(args[0])
|
||||
switch fld := args[1].(type) {
|
||||
case *sql.Value:
|
||||
return doc.Get(fld.ID).Data(), nil
|
||||
case string:
|
||||
return doc.Get(fld).Data(), nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
56
util/fncs/get_test.go
Normal file
56
util/fncs/get_test.go
Normal file
|
@ -0,0 +1,56 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/abcum/surreal/sql"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
|
||||
var res interface{}
|
||||
|
||||
var doc = map[string]interface{}{
|
||||
"object": map[string]interface{}{
|
||||
"test": "ok",
|
||||
},
|
||||
"string": "test",
|
||||
"bool": true,
|
||||
"int": 13,
|
||||
}
|
||||
|
||||
Convey("get(a, b) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "get", doc, &sql.Value{"object.test"})
|
||||
So(res, ShouldEqual, "ok")
|
||||
res, _ = Run(context.Background(), "get", doc, "object.test")
|
||||
So(res, ShouldEqual, "ok")
|
||||
res, _ = Run(context.Background(), "get", doc, "string")
|
||||
So(res, ShouldEqual, "test")
|
||||
res, _ = Run(context.Background(), "get", doc, "bool")
|
||||
So(res, ShouldEqual, true)
|
||||
res, _ = Run(context.Background(), "get", doc, "int")
|
||||
So(res, ShouldEqual, 13)
|
||||
res, _ = Run(context.Background(), "get", doc, "err")
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "get", doc, nil)
|
||||
So(res, ShouldEqual, nil)
|
||||
})
|
||||
|
||||
}
|
56
util/fncs/hash.go
Normal file
56
util/fncs/hash.go
Normal file
|
@ -0,0 +1,56 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/md5"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"encoding/hex"
|
||||
)
|
||||
|
||||
func hashMd5(ctx context.Context, args ...interface{}) (string, error) {
|
||||
v, _ := ensureString(args[0])
|
||||
h := md5.New()
|
||||
h.Write([]byte(v))
|
||||
s := h.Sum(nil)
|
||||
return hex.EncodeToString(s), nil
|
||||
}
|
||||
|
||||
func hashSha1(ctx context.Context, args ...interface{}) (string, error) {
|
||||
v, _ := ensureString(args[0])
|
||||
h := sha1.New()
|
||||
h.Write([]byte(v))
|
||||
s := h.Sum(nil)
|
||||
return hex.EncodeToString(s), nil
|
||||
}
|
||||
|
||||
func hashSha256(ctx context.Context, args ...interface{}) (string, error) {
|
||||
v, _ := ensureString(args[0])
|
||||
h := sha256.New()
|
||||
h.Write([]byte(v))
|
||||
s := h.Sum(nil)
|
||||
return hex.EncodeToString(s), nil
|
||||
}
|
||||
|
||||
func hashSha512(ctx context.Context, args ...interface{}) (string, error) {
|
||||
v, _ := ensureString(args[0])
|
||||
h := sha512.New()
|
||||
h.Write([]byte(v))
|
||||
s := h.Sum(nil)
|
||||
return hex.EncodeToString(s), nil
|
||||
}
|
50
util/fncs/hash_test.go
Normal file
50
util/fncs/hash_test.go
Normal file
|
@ -0,0 +1,50 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestHash(t *testing.T) {
|
||||
|
||||
Convey("hash.md5(a) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "hash.md5", "test")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
So(res, ShouldEqual, "098f6bcd4621d373cade4e832627b4f6")
|
||||
})
|
||||
|
||||
Convey("hash.sha1(a) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "hash.sha1", "test")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
So(res, ShouldEqual, "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3")
|
||||
})
|
||||
|
||||
Convey("hash.sha256(a) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "hash.sha256", "test")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
So(res, ShouldEqual, "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08")
|
||||
})
|
||||
|
||||
Convey("hash.sha512(a) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "hash.sha512", "test")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
So(res, ShouldEqual, "ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff")
|
||||
})
|
||||
|
||||
}
|
210
util/fncs/http.go
Normal file
210
util/fncs/http.go
Normal file
|
@ -0,0 +1,210 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"encoding/json"
|
||||
|
||||
"golang.org/x/net/context/ctxhttp"
|
||||
|
||||
"github.com/abcum/surreal/util/build"
|
||||
"github.com/abcum/surreal/util/hook"
|
||||
)
|
||||
|
||||
type opts map[string]interface{}
|
||||
|
||||
var version = build.GetInfo().Ver
|
||||
|
||||
var httpResponseError = errors.New("HTTP response error")
|
||||
|
||||
func httpHead(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
return runSync(ctx, "HEAD", args...)
|
||||
}
|
||||
|
||||
func httpGet(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
return runSync(ctx, "GET", args...)
|
||||
}
|
||||
|
||||
func httpPut(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
return runSync(ctx, "PUT", args...)
|
||||
}
|
||||
|
||||
func httpPost(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
return runSync(ctx, "POST", args...)
|
||||
}
|
||||
|
||||
func httpPatch(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
return runSync(ctx, "PATCH", args...)
|
||||
}
|
||||
|
||||
func httpDelete(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
return runSync(ctx, "DELETE", args...)
|
||||
}
|
||||
|
||||
func httpAsyncHead(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
return runAsync(ctx, "HEAD", args...)
|
||||
}
|
||||
|
||||
func httpAsyncGet(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
return runAsync(ctx, "GET", args...)
|
||||
}
|
||||
|
||||
func httpAsyncPut(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
return runAsync(ctx, "PUT", args...)
|
||||
}
|
||||
|
||||
func httpAsyncPost(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
return runAsync(ctx, "POST", args...)
|
||||
}
|
||||
|
||||
func httpAsyncPatch(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
return runAsync(ctx, "PATCH", args...)
|
||||
}
|
||||
|
||||
func httpAsyncDelete(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
return runAsync(ctx, "DELETE", args...)
|
||||
}
|
||||
|
||||
func runSync(ctx context.Context, met string, args ...interface{}) (interface{}, error) {
|
||||
url, bdy, opt := httpCnf(met, args...)
|
||||
out, _ := httpRes(ctx, met, url, bdy, opt)
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func runAsync(ctx context.Context, met string, args ...interface{}) (interface{}, error) {
|
||||
url, bdy, opt := httpCnf(met, args...)
|
||||
ctx = context.Background()
|
||||
go hook.NewBackoff(5, 5, 10*time.Second).Run(ctx, func() error {
|
||||
return httpErr(httpReq(ctx, met, url, bdy, opt))
|
||||
})
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func httpCnf(met string, args ...interface{}) (url string, bdy io.Reader, opt opts) {
|
||||
var bit []byte
|
||||
switch met {
|
||||
case "HEAD", "GET", "DELETE":
|
||||
switch len(args) {
|
||||
case 1:
|
||||
url, _ = ensureString(args[0])
|
||||
case 2:
|
||||
url, _ = ensureString(args[0])
|
||||
opt, _ = ensureObject(args[1])
|
||||
}
|
||||
case "PUT", "POST", "PATCH":
|
||||
switch len(args) {
|
||||
case 1:
|
||||
url, _ = ensureString(args[0])
|
||||
case 2:
|
||||
url, _ = ensureString(args[0])
|
||||
switch v := args[1].(type) {
|
||||
case []interface{}, map[string]interface{}:
|
||||
bit, _ = json.Marshal(v)
|
||||
default:
|
||||
bit, _ = ensureBytes(v)
|
||||
}
|
||||
case 3:
|
||||
url, _ = ensureString(args[0])
|
||||
switch v := args[1].(type) {
|
||||
case []interface{}, map[string]interface{}:
|
||||
bit, _ = json.Marshal(v)
|
||||
default:
|
||||
bit, _ = ensureBytes(v)
|
||||
}
|
||||
opt, _ = ensureObject(args[2])
|
||||
}
|
||||
}
|
||||
return url, bytes.NewReader(bit), opt
|
||||
}
|
||||
|
||||
func httpReq(ctx context.Context, met, url string, body io.Reader, conf opts) (*http.Response, error) {
|
||||
|
||||
cli := new(http.Client)
|
||||
|
||||
req, err := http.NewRequest(met, url, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("User-Agent", "SurrealDB HTTP/"+version)
|
||||
|
||||
if val, ok := conf["auth"]; ok {
|
||||
if opt, ok := ensureObject(val); ok {
|
||||
user, _ := ensureString(opt["user"])
|
||||
pass, _ := ensureString(opt["pass"])
|
||||
req.SetBasicAuth(user, pass)
|
||||
}
|
||||
}
|
||||
|
||||
if val, ok := conf["head"]; ok {
|
||||
if opt, ok := ensureObject(val); ok {
|
||||
for key, v := range opt {
|
||||
head, _ := ensureString(v)
|
||||
req.Header.Set(key, head)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res, err := ctxhttp.Do(ctx, cli, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
|
||||
}
|
||||
|
||||
func httpRes(ctx context.Context, met, url string, body io.Reader, conf opts) (interface{}, error) {
|
||||
|
||||
var out interface{}
|
||||
|
||||
res, err := httpReq(ctx, met, url, body, conf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bdy, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(bdy, &out)
|
||||
if err != nil {
|
||||
if len(bdy) != 0 {
|
||||
return bdy, nil
|
||||
}
|
||||
}
|
||||
|
||||
return out, nil
|
||||
|
||||
}
|
||||
|
||||
func httpErr(res *http.Response, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if res.StatusCode >= 500 {
|
||||
return httpResponseError
|
||||
}
|
||||
return nil
|
||||
}
|
158
util/fncs/http_test.go
Normal file
158
util/fncs/http_test.go
Normal file
|
@ -0,0 +1,158 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestHttp(t *testing.T) {
|
||||
|
||||
var res interface{}
|
||||
var jsn = `{"test":true, "temp":"text"}`
|
||||
var obj = map[string]interface{}{"temp": "text", "test": true}
|
||||
var txt = `<!doctype html><html><head></head><body></body></html>`
|
||||
var opt = map[string]interface{}{
|
||||
"auth": map[string]interface{}{"user": "u", "pass": "p"},
|
||||
"head": map[string]interface{}{"x-test": true},
|
||||
}
|
||||
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.Method {
|
||||
case "HEAD", "DELETE":
|
||||
// Return nothing
|
||||
case "GET":
|
||||
fmt.Fprint(w, txt)
|
||||
case "PUT", "POST", "PATCH":
|
||||
io.Copy(w, r.Body)
|
||||
}
|
||||
}))
|
||||
|
||||
defer srv.Close()
|
||||
|
||||
Convey("http.head(a) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "http.head", srv.URL)
|
||||
So(res, ShouldResemble, nil)
|
||||
})
|
||||
|
||||
Convey("http.get(a) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "http.get", srv.URL)
|
||||
So(res, ShouldResemble, []byte(txt))
|
||||
res, _ = Run(context.Background(), "http.get", srv.URL, opt)
|
||||
So(res, ShouldResemble, []byte(txt))
|
||||
})
|
||||
|
||||
Convey("http.put(a) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "http.put", srv.URL)
|
||||
So(res, ShouldResemble, nil)
|
||||
res, _ = Run(context.Background(), "http.put", srv.URL, txt)
|
||||
So(res, ShouldResemble, []byte(txt))
|
||||
res, _ = Run(context.Background(), "http.put", srv.URL, jsn)
|
||||
So(res, ShouldResemble, obj)
|
||||
res, _ = Run(context.Background(), "http.put", srv.URL, jsn, opt)
|
||||
So(res, ShouldResemble, obj)
|
||||
})
|
||||
|
||||
Convey("http.post(a) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "http.post", srv.URL)
|
||||
So(res, ShouldResemble, nil)
|
||||
res, _ = Run(context.Background(), "http.post", srv.URL, txt)
|
||||
So(res, ShouldResemble, []byte(txt))
|
||||
res, _ = Run(context.Background(), "http.post", srv.URL, jsn)
|
||||
So(res, ShouldResemble, obj)
|
||||
res, _ = Run(context.Background(), "http.post", srv.URL, jsn, opt)
|
||||
So(res, ShouldResemble, obj)
|
||||
})
|
||||
|
||||
Convey("http.patch(a) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "http.patch", srv.URL)
|
||||
So(res, ShouldResemble, nil)
|
||||
res, _ = Run(context.Background(), "http.patch", srv.URL, txt)
|
||||
So(res, ShouldResemble, []byte(txt))
|
||||
res, _ = Run(context.Background(), "http.patch", srv.URL, jsn)
|
||||
So(res, ShouldResemble, obj)
|
||||
res, _ = Run(context.Background(), "http.patch", srv.URL, jsn, opt)
|
||||
So(res, ShouldResemble, obj)
|
||||
})
|
||||
|
||||
Convey("http.delete(a) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "http.delete", srv.URL)
|
||||
So(res, ShouldResemble, nil)
|
||||
res, _ = Run(context.Background(), "http.delete", srv.URL, opt)
|
||||
So(res, ShouldResemble, nil)
|
||||
})
|
||||
|
||||
Convey("http.async.head(a) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "http.async.head", srv.URL)
|
||||
So(res, ShouldResemble, nil)
|
||||
res, _ = Run(context.Background(), "http.async.head", srv.URL, opt)
|
||||
So(res, ShouldResemble, nil)
|
||||
})
|
||||
|
||||
Convey("http.async.get(a) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "http.async.get", srv.URL)
|
||||
So(res, ShouldResemble, nil)
|
||||
res, _ = Run(context.Background(), "http.async.get", srv.URL, opt)
|
||||
So(res, ShouldResemble, nil)
|
||||
})
|
||||
|
||||
Convey("http.async.put(a) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "http.async.put", srv.URL)
|
||||
So(res, ShouldResemble, nil)
|
||||
res, _ = Run(context.Background(), "http.async.put", srv.URL, txt)
|
||||
So(res, ShouldResemble, nil)
|
||||
res, _ = Run(context.Background(), "http.async.put", srv.URL, jsn)
|
||||
So(res, ShouldResemble, nil)
|
||||
res, _ = Run(context.Background(), "http.async.put", srv.URL, jsn, opt)
|
||||
So(res, ShouldResemble, nil)
|
||||
})
|
||||
|
||||
Convey("http.async.post(a) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "http.async.post", srv.URL)
|
||||
So(res, ShouldResemble, nil)
|
||||
res, _ = Run(context.Background(), "http.async.post", srv.URL, txt)
|
||||
So(res, ShouldResemble, nil)
|
||||
res, _ = Run(context.Background(), "http.async.post", srv.URL, jsn)
|
||||
So(res, ShouldResemble, nil)
|
||||
res, _ = Run(context.Background(), "http.async.post", srv.URL, jsn, opt)
|
||||
So(res, ShouldResemble, nil)
|
||||
})
|
||||
|
||||
Convey("http.async.patch(a) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "http.async.patch", srv.URL)
|
||||
So(res, ShouldResemble, nil)
|
||||
res, _ = Run(context.Background(), "http.async.patch", srv.URL, txt)
|
||||
So(res, ShouldResemble, nil)
|
||||
res, _ = Run(context.Background(), "http.async.patch", srv.URL, jsn)
|
||||
So(res, ShouldResemble, nil)
|
||||
res, _ = Run(context.Background(), "http.async.patch", srv.URL, jsn, opt)
|
||||
So(res, ShouldResemble, nil)
|
||||
})
|
||||
|
||||
Convey("http.async.delete(a) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "http.async.delete", srv.URL)
|
||||
So(res, ShouldResemble, nil)
|
||||
res, _ = Run(context.Background(), "http.async.delete", srv.URL, opt)
|
||||
So(res, ShouldResemble, nil)
|
||||
})
|
||||
|
||||
}
|
26
util/fncs/if.go
Normal file
26
util/fncs/if.go
Normal file
|
@ -0,0 +1,26 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
func ifel(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
if val, ok := ensureBool(args[0]); ok && val {
|
||||
return args[1], nil
|
||||
}
|
||||
return args[2], nil
|
||||
}
|
41
util/fncs/if_test.go
Normal file
41
util/fncs/if_test.go
Normal file
|
@ -0,0 +1,41 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestIf(t *testing.T) {
|
||||
|
||||
var res interface{}
|
||||
|
||||
Convey("if(a, b, c) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "if", true, "yes", "no")
|
||||
So(res, ShouldEqual, "yes")
|
||||
res, _ = Run(context.Background(), "if", "true", "yes", "no")
|
||||
So(res, ShouldEqual, "yes")
|
||||
res, _ = Run(context.Background(), "if", false, "yes", "no")
|
||||
So(res, ShouldEqual, "no")
|
||||
res, _ = Run(context.Background(), "if", "false", "yes", "no")
|
||||
So(res, ShouldEqual, "no")
|
||||
res, _ = Run(context.Background(), "if", "something", "yes", "no")
|
||||
So(res, ShouldEqual, "no")
|
||||
})
|
||||
|
||||
}
|
32
util/fncs/json.go
Normal file
32
util/fncs/json.go
Normal file
|
@ -0,0 +1,32 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
func jsonDecode(ctx context.Context, args ...interface{}) (out interface{}, err error) {
|
||||
bit, _ := ensureBytes(args[0])
|
||||
json.Unmarshal(bit, &out)
|
||||
return
|
||||
}
|
||||
|
||||
func jsonEncode(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
bit, _ := json.Marshal(args[0])
|
||||
return bit, nil
|
||||
}
|
48
util/fncs/json_test.go
Normal file
48
util/fncs/json_test.go
Normal file
|
@ -0,0 +1,48 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestJson(t *testing.T) {
|
||||
|
||||
var res interface{}
|
||||
|
||||
Convey("json.decode(a) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "json.decode", "true")
|
||||
So(res, ShouldResemble, true)
|
||||
res, _ = Run(context.Background(), "json.decode", "13579")
|
||||
So(res, ShouldResemble, float64(13579))
|
||||
res, _ = Run(context.Background(), "json.decode", `{"test":true}`)
|
||||
So(res, ShouldResemble, map[string]interface{}{
|
||||
"test": true,
|
||||
})
|
||||
})
|
||||
|
||||
Convey("json.encode(a) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "json.encode", true)
|
||||
So(res, ShouldResemble, []byte("true"))
|
||||
res, _ = Run(context.Background(), "json.encode", 13579)
|
||||
So(res, ShouldResemble, []byte("13579"))
|
||||
res, _ = Run(context.Background(), "json.encode", map[string]interface{}{"test": true})
|
||||
So(res, ShouldResemble, []byte(`{"test":true}`))
|
||||
})
|
||||
|
||||
}
|
163
util/fncs/math.go
Normal file
163
util/fncs/math.go
Normal file
|
@ -0,0 +1,163 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/abcum/surreal/util/math"
|
||||
)
|
||||
|
||||
func mathAbs(ctx context.Context, args ...interface{}) (out interface{}, err error) {
|
||||
if val, ok := ensureFloat(args[0]); ok {
|
||||
return outputFloat(math.Abs(val))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func mathBottom(ctx context.Context, args ...interface{}) (out interface{}, err error) {
|
||||
vals := ensureFloats(args[0])
|
||||
if take, ok := ensureInt(args[1]); ok {
|
||||
return math.Bottom(vals, int(take)), nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func mathCeil(ctx context.Context, args ...interface{}) (out interface{}, err error) {
|
||||
if val, ok := ensureFloat(args[0]); ok {
|
||||
return outputFloat(math.Ceil(val))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func mathCorrelation(ctx context.Context, args ...interface{}) (out interface{}, err error) {
|
||||
a := ensureFloats(args[0])
|
||||
b := ensureFloats(args[1])
|
||||
return outputFloat(math.Correlation(a, b))
|
||||
}
|
||||
|
||||
func mathCovariance(ctx context.Context, args ...interface{}) (out interface{}, err error) {
|
||||
a := ensureFloats(args[0])
|
||||
b := ensureFloats(args[1])
|
||||
return outputFloat(math.Covariance(a, b))
|
||||
}
|
||||
|
||||
func mathFloor(ctx context.Context, args ...interface{}) (out interface{}, err error) {
|
||||
if val, ok := ensureFloat(args[0]); ok {
|
||||
return outputFloat(math.Floor(val))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func mathGeometricmean(ctx context.Context, args ...interface{}) (out interface{}, err error) {
|
||||
vals := ensureFloats(args[0])
|
||||
return outputFloat(math.GeometricMean(vals))
|
||||
}
|
||||
|
||||
func mathHarmonicmean(ctx context.Context, args ...interface{}) (out interface{}, err error) {
|
||||
vals := ensureFloats(args[0])
|
||||
return outputFloat(math.HarmonicMean(vals))
|
||||
}
|
||||
|
||||
func mathInterquartile(ctx context.Context, args ...interface{}) (out interface{}, err error) {
|
||||
vals := ensureFloats(args[0])
|
||||
return outputFloat(math.InterQuartileRange(vals))
|
||||
}
|
||||
|
||||
func mathMax(ctx context.Context, args ...interface{}) (out interface{}, err error) {
|
||||
vals := ensureFloats(args[0])
|
||||
return outputFloat(math.Max(vals))
|
||||
}
|
||||
|
||||
func mathMean(ctx context.Context, args ...interface{}) (out interface{}, err error) {
|
||||
vals := ensureFloats(args[0])
|
||||
return outputFloat(math.Mean(vals))
|
||||
}
|
||||
|
||||
func mathMedian(ctx context.Context, args ...interface{}) (out interface{}, err error) {
|
||||
vals := ensureFloats(args[0])
|
||||
return outputFloat(math.Median(vals))
|
||||
}
|
||||
|
||||
func mathMidhinge(ctx context.Context, args ...interface{}) (out interface{}, err error) {
|
||||
vals := ensureFloats(args[0])
|
||||
return outputFloat(math.Midhinge(vals))
|
||||
}
|
||||
|
||||
func mathMin(ctx context.Context, args ...interface{}) (out interface{}, err error) {
|
||||
vals := ensureFloats(args[0])
|
||||
return outputFloat(math.Min(vals))
|
||||
}
|
||||
|
||||
func mathMode(ctx context.Context, args ...interface{}) (out []float64, err error) {
|
||||
vals := ensureFloats(args[0])
|
||||
return math.Mode(vals), nil
|
||||
}
|
||||
|
||||
func mathPercentile(ctx context.Context, args ...interface{}) (out interface{}, err error) {
|
||||
vals := ensureFloats(args[0])
|
||||
if perc, ok := ensureFloat(args[1]); ok {
|
||||
return outputFloat(math.Percentile(vals, perc))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func mathRound(ctx context.Context, args ...interface{}) (out interface{}, err error) {
|
||||
if val, ok := ensureFloat(args[0]); ok {
|
||||
return outputFloat(math.Round(val))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func mathSample(ctx context.Context, args ...interface{}) (out interface{}, err error) {
|
||||
vals := ensureFloats(args[0])
|
||||
if take, ok := ensureInt(args[1]); ok {
|
||||
return math.Sample(vals, int(take)), nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func mathSpread(ctx context.Context, args ...interface{}) (out interface{}, err error) {
|
||||
vals := ensureFloats(args[0])
|
||||
return outputFloat(math.Spread(vals))
|
||||
}
|
||||
|
||||
func mathStddev(ctx context.Context, args ...interface{}) (out interface{}, err error) {
|
||||
vals := ensureFloats(args[0])
|
||||
return outputFloat(math.PopulationStandardDeviation(vals))
|
||||
}
|
||||
|
||||
func mathSum(ctx context.Context, args ...interface{}) (out interface{}, err error) {
|
||||
vals := ensureFloats(args[0])
|
||||
return outputFloat(math.Sum(vals))
|
||||
}
|
||||
|
||||
func mathTop(ctx context.Context, args ...interface{}) (out interface{}, err error) {
|
||||
vals := ensureFloats(args[0])
|
||||
if take, ok := ensureInt(args[1]); ok {
|
||||
return math.Top(vals, int(take)), nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func mathTrimean(ctx context.Context, args ...interface{}) (out interface{}, err error) {
|
||||
vals := ensureFloats(args[0])
|
||||
return outputFloat(math.Trimean(vals))
|
||||
}
|
||||
|
||||
func mathVariance(ctx context.Context, args ...interface{}) (out interface{}, err error) {
|
||||
vals := ensureFloats(args[0])
|
||||
return outputFloat(math.PopulationVariance(vals))
|
||||
}
|
264
util/fncs/math_test.go
Normal file
264
util/fncs/math_test.go
Normal file
|
@ -0,0 +1,264 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestMath(t *testing.T) {
|
||||
|
||||
var res interface{}
|
||||
|
||||
var test = []interface{}{int(1), int64(3), float32(4.5), float64(3.5)}
|
||||
var testA = []interface{}{int(1), int64(3), float32(4.5), float64(3.5)}
|
||||
var testB = []interface{}{int(5), int64(9), float32(2.5), float64(6.5)}
|
||||
var testC = []interface{}{int(5), int64(5), float32(2.5), float64(6.5)}
|
||||
|
||||
Convey("math.abs() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "math.abs", "test")
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "math.abs", 10)
|
||||
So(res, ShouldEqual, 10)
|
||||
res, _ = Run(context.Background(), "math.abs", -1.5)
|
||||
So(res, ShouldEqual, 1.5)
|
||||
})
|
||||
|
||||
Convey("math.bottom() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "math.bottom", "test", 2)
|
||||
So(res, ShouldHaveLength, 0)
|
||||
res, _ = Run(context.Background(), "math.bottom", testC, "oops")
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "math.bottom", testC, 2)
|
||||
So(res, ShouldHaveSameTypeAs, []float64{})
|
||||
So(res, ShouldContain, 2.5)
|
||||
So(res, ShouldContain, 5.0)
|
||||
res, _ = Run(context.Background(), "math.bottom", 13, 2)
|
||||
So(res, ShouldHaveSameTypeAs, []float64{})
|
||||
So(res, ShouldContain, 13.0)
|
||||
})
|
||||
|
||||
Convey("math.ceil() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "math.ceil", "test")
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "math.ceil", 10)
|
||||
So(res, ShouldEqual, 10)
|
||||
res, _ = Run(context.Background(), "math.ceil", 1.5)
|
||||
So(res, ShouldEqual, 2)
|
||||
})
|
||||
|
||||
Convey("math.correlation() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "math.correlation", "test", "test")
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "math.correlation", 1234, 1234)
|
||||
So(res, ShouldEqual, 0)
|
||||
res, _ = Run(context.Background(), "math.correlation", testA, testB)
|
||||
So(res, ShouldEqual, -0.24945922497781908)
|
||||
})
|
||||
|
||||
Convey("math.covariance() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "math.covariance", "test", "test")
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "math.covariance", 1234, 1234)
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "math.covariance", testA, testB)
|
||||
So(res, ShouldEqual, -1)
|
||||
})
|
||||
|
||||
Convey("math.floor() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "math.floor", "test")
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "math.floor", 10)
|
||||
So(res, ShouldEqual, 10)
|
||||
res, _ = Run(context.Background(), "math.floor", 1.5)
|
||||
So(res, ShouldEqual, 1)
|
||||
})
|
||||
|
||||
Convey("math.geometricmean() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "math.geometricmean", "test")
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "math.geometricmean", 10)
|
||||
So(res, ShouldEqual, 10)
|
||||
res, _ = Run(context.Background(), "math.geometricmean", test)
|
||||
So(res, ShouldEqual, 2.621805397514041)
|
||||
})
|
||||
|
||||
Convey("math.harmonicmean() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "math.harmonicmean", "test")
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "math.harmonicmean", 10)
|
||||
So(res, ShouldEqual, 10)
|
||||
res, _ = Run(context.Background(), "math.harmonicmean", test)
|
||||
So(res, ShouldEqual, 2.172413793103449)
|
||||
})
|
||||
|
||||
Convey("math.interquartile() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "math.interquartile", "test")
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "math.interquartile", 10)
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "math.interquartile", test)
|
||||
So(res, ShouldEqual, 2)
|
||||
})
|
||||
|
||||
Convey("math.max() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "math.max", "test")
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "math.max", 10)
|
||||
So(res, ShouldEqual, 10)
|
||||
res, _ = Run(context.Background(), "math.max", test)
|
||||
So(res, ShouldEqual, 4.5)
|
||||
})
|
||||
|
||||
Convey("math.mean() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "math.mean", "test")
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "math.mean", 10)
|
||||
So(res, ShouldEqual, 10)
|
||||
res, _ = Run(context.Background(), "math.mean", testA, testB)
|
||||
So(res, ShouldEqual, 3)
|
||||
})
|
||||
|
||||
Convey("math.median() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "math.median", "test")
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "math.median", 10)
|
||||
So(res, ShouldEqual, 10)
|
||||
res, _ = Run(context.Background(), "math.median", testA, testB)
|
||||
So(res, ShouldEqual, 3.25)
|
||||
})
|
||||
|
||||
Convey("math.midhinge() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "math.midhinge", "test")
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "math.midhinge", 10)
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "math.midhinge", test)
|
||||
So(res, ShouldEqual, 3)
|
||||
})
|
||||
|
||||
Convey("math.min() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "math.min", "test")
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "math.min", 10)
|
||||
So(res, ShouldEqual, 10)
|
||||
res, _ = Run(context.Background(), "math.min", test)
|
||||
So(res, ShouldEqual, 1)
|
||||
})
|
||||
|
||||
Convey("math.mode() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "math.mode", "test")
|
||||
So(res, ShouldHaveLength, 0)
|
||||
res, _ = Run(context.Background(), "math.mode", testC)
|
||||
So(res, ShouldResemble, []float64{5})
|
||||
res, _ = Run(context.Background(), "math.mode", 1)
|
||||
So(res, ShouldResemble, []float64{1})
|
||||
})
|
||||
|
||||
Convey("math.percentile() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "math.percentile", "test", 90)
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "math.percentile", 10, "oops")
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "math.percentile", 10, 90)
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "math.percentile", test, 90)
|
||||
So(res, ShouldEqual, 4)
|
||||
})
|
||||
|
||||
Convey("math.round() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "math.round", "test")
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "math.round", 1.4)
|
||||
So(res, ShouldEqual, 1)
|
||||
res, _ = Run(context.Background(), "math.round", 1.5)
|
||||
So(res, ShouldEqual, 2)
|
||||
})
|
||||
|
||||
Convey("math.sample() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "math.sample", "test", 3)
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "math.sample", 10, "oops")
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "math.sample", 10, 3)
|
||||
So(res, ShouldResemble, []float64{10})
|
||||
res, _ = Run(context.Background(), "math.sample", test, 3)
|
||||
So(res, ShouldHaveLength, 3)
|
||||
})
|
||||
|
||||
Convey("math.spread() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "math.spread", "test")
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "math.spread", 10)
|
||||
So(res, ShouldEqual, 0)
|
||||
res, _ = Run(context.Background(), "math.spread", test)
|
||||
So(res, ShouldEqual, 4.5)
|
||||
})
|
||||
|
||||
Convey("math.stddev() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "math.stddev", "test")
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "math.stddev", 10)
|
||||
So(res, ShouldEqual, 0)
|
||||
res, _ = Run(context.Background(), "math.stddev", test)
|
||||
So(res, ShouldEqual, 1.2747548783981961)
|
||||
})
|
||||
|
||||
Convey("math.sum() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "math.sum", "test")
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "math.sum", 1234)
|
||||
So(res, ShouldEqual, 1234)
|
||||
res, _ = Run(context.Background(), "math.sum", []interface{}{int(1), int64(3), float32(4.5), float64(3.5)})
|
||||
So(res, ShouldEqual, 12)
|
||||
})
|
||||
|
||||
Convey("math.top() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "math.top", "test", 2)
|
||||
So(res, ShouldHaveSameTypeAs, []float64{})
|
||||
So(res, ShouldHaveLength, 0)
|
||||
res, _ = Run(context.Background(), "math.top", testC, "oops")
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "math.top", testC, 2)
|
||||
So(res, ShouldHaveSameTypeAs, []float64{})
|
||||
So(res, ShouldContain, 6.5)
|
||||
So(res, ShouldContain, 5.0)
|
||||
res, _ = Run(context.Background(), "math.top", 13, 2)
|
||||
So(res, ShouldHaveSameTypeAs, []float64{})
|
||||
So(res, ShouldContain, 13.0)
|
||||
})
|
||||
|
||||
Convey("math.trimean() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "math.trimean", "test")
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "math.trimean", 10)
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "math.trimean", test)
|
||||
So(res, ShouldEqual, 3.125)
|
||||
})
|
||||
|
||||
Convey("math.variance() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "math.variance", "test")
|
||||
So(res, ShouldEqual, nil)
|
||||
res, _ = Run(context.Background(), "math.variance", 10)
|
||||
So(res, ShouldEqual, 0)
|
||||
res, _ = Run(context.Background(), "math.variance", test)
|
||||
So(res, ShouldEqual, 1.625)
|
||||
})
|
||||
|
||||
}
|
46
util/fncs/model.go
Normal file
46
util/fncs/model.go
Normal file
|
@ -0,0 +1,46 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/abcum/surreal/sql"
|
||||
)
|
||||
|
||||
func model(ctx context.Context, args ...interface{}) (*sql.Model, error) {
|
||||
tb, _ := ensureString(args[0])
|
||||
switch len(args) {
|
||||
case 2:
|
||||
if max, ok := ensureFloat(args[1]); ok {
|
||||
return sql.NewModel(tb, 0, 0, max), nil
|
||||
}
|
||||
case 3:
|
||||
if min, ok := ensureFloat(args[1]); ok {
|
||||
if max, ok := ensureFloat(args[2]); ok {
|
||||
return sql.NewModel(tb, min, 1, max), nil
|
||||
}
|
||||
}
|
||||
case 4:
|
||||
if min, ok := ensureFloat(args[1]); ok {
|
||||
if inc, ok := ensureFloat(args[2]); ok {
|
||||
if max, ok := ensureFloat(args[3]); ok {
|
||||
return sql.NewModel(tb, min, inc, max), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
55
util/fncs/model_test.go
Normal file
55
util/fncs/model_test.go
Normal file
|
@ -0,0 +1,55 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/abcum/surreal/sql"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestModel(t *testing.T) {
|
||||
|
||||
var res interface{}
|
||||
|
||||
Convey("model(a) errors properly", t, func() {
|
||||
res, _ = Run(context.Background(), "model", "test")
|
||||
So(res, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("model(a, b) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "model", 1, 10)
|
||||
So(res, ShouldResemble, sql.NewModel("1", 0, 0, 10))
|
||||
res, _ = Run(context.Background(), "model", "test", 10)
|
||||
So(res, ShouldResemble, sql.NewModel("test", 0, 0, 10))
|
||||
})
|
||||
|
||||
Convey("model(a, b, c) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "model", 1, 10, 20)
|
||||
So(res, ShouldResemble, sql.NewModel("1", 10, 1, 20))
|
||||
res, _ = Run(context.Background(), "model", "test", 10, 20)
|
||||
So(res, ShouldResemble, sql.NewModel("test", 10, 1, 20))
|
||||
})
|
||||
|
||||
Convey("model(a, b, c, d) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "model", 1, 10, 0.5, 20)
|
||||
So(res, ShouldResemble, sql.NewModel("1", 10, 0.5, 20))
|
||||
res, _ = Run(context.Background(), "model", "test", 10, 0.5, 20)
|
||||
So(res, ShouldResemble, sql.NewModel("test", 10, 0.5, 20))
|
||||
})
|
||||
|
||||
}
|
207
util/fncs/rand.go
Normal file
207
util/fncs/rand.go
Normal file
|
@ -0,0 +1,207 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/abcum/surreal/util/fake"
|
||||
)
|
||||
|
||||
func rand(ctx context.Context, args ...interface{}) (float64, error) {
|
||||
return fake.DecimalBetween(0, 1), nil
|
||||
}
|
||||
|
||||
func randBool(ctx context.Context, args ...interface{}) (bool, error) {
|
||||
return fake.Bool(), nil
|
||||
}
|
||||
|
||||
func randUuid(ctx context.Context, args ...interface{}) (string, error) {
|
||||
return fake.Uuid(), nil
|
||||
}
|
||||
|
||||
func randEnum(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
switch len(args) {
|
||||
case 0:
|
||||
return nil, nil
|
||||
default:
|
||||
return args[fake.IntegerBetween(0, len(args))], nil
|
||||
}
|
||||
}
|
||||
|
||||
func randTime(ctx context.Context, args ...interface{}) (time.Time, error) {
|
||||
switch len(args) {
|
||||
case 2:
|
||||
if b, ok := ensureTime(args[0]); ok {
|
||||
if e, ok := ensureTime(args[1]); ok {
|
||||
return fake.TimeBetween(b, e), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return fake.Time(), nil
|
||||
}
|
||||
|
||||
func randString(ctx context.Context, args ...interface{}) (string, error) {
|
||||
switch len(args) {
|
||||
case 1:
|
||||
if l, ok := ensureInt(args[0]); ok {
|
||||
return fake.StringLength(int(l)), nil
|
||||
}
|
||||
case 2:
|
||||
if b, ok := ensureInt(args[0]); ok {
|
||||
if e, ok := ensureInt(args[1]); ok {
|
||||
return fake.StringBetween(int(b), int(e)), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return fake.String(), nil
|
||||
}
|
||||
|
||||
func randInteger(ctx context.Context, args ...interface{}) (float64, error) {
|
||||
switch len(args) {
|
||||
case 2:
|
||||
if b, ok := ensureInt(args[0]); ok {
|
||||
if e, ok := ensureInt(args[1]); ok {
|
||||
return float64(fake.IntegerBetween(int(b), int(e))), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return float64(fake.Integer()), nil
|
||||
}
|
||||
|
||||
func randDecimal(ctx context.Context, args ...interface{}) (float64, error) {
|
||||
switch len(args) {
|
||||
case 2:
|
||||
if b, ok := ensureFloat(args[0]); ok {
|
||||
if e, ok := ensureFloat(args[1]); ok {
|
||||
return fake.DecimalBetween(b, e), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return fake.Decimal(), nil
|
||||
}
|
||||
|
||||
func randWord(ctx context.Context, args ...interface{}) (string, error) {
|
||||
return fake.Word(), nil
|
||||
}
|
||||
|
||||
func randSentence(ctx context.Context, args ...interface{}) (string, error) {
|
||||
switch len(args) {
|
||||
case 2:
|
||||
if b, ok := ensureInt(args[0]); ok {
|
||||
if e, ok := ensureInt(args[1]); ok {
|
||||
return fake.SentenceBetween(int(b), int(e)), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return fake.Sentence(), nil
|
||||
}
|
||||
|
||||
func randParagraph(ctx context.Context, args ...interface{}) (string, error) {
|
||||
switch len(args) {
|
||||
case 2:
|
||||
if b, ok := ensureInt(args[0]); ok {
|
||||
if e, ok := ensureInt(args[1]); ok {
|
||||
return fake.ParagraphBetween(int(b), int(e)), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return fake.Paragraph(), nil
|
||||
}
|
||||
|
||||
func randPersonEmail(ctx context.Context, args ...interface{}) (string, error) {
|
||||
return fake.PersonEmail(), nil
|
||||
}
|
||||
|
||||
func randPersonPhone(ctx context.Context, args ...interface{}) (string, error) {
|
||||
return fake.PersonPhone(), nil
|
||||
}
|
||||
|
||||
func randPersonFullname(ctx context.Context, args ...interface{}) (string, error) {
|
||||
return fake.PersonFullname(), nil
|
||||
}
|
||||
|
||||
func randPersonFirstname(ctx context.Context, args ...interface{}) (string, error) {
|
||||
return fake.PersonFirstname(), nil
|
||||
}
|
||||
|
||||
func randPersonLastname(ctx context.Context, args ...interface{}) (string, error) {
|
||||
return fake.PersonLastname(), nil
|
||||
}
|
||||
|
||||
func randPersonUsername(ctx context.Context, args ...interface{}) (string, error) {
|
||||
return fake.PersonUsername(), nil
|
||||
}
|
||||
|
||||
func randPersonJobtitle(ctx context.Context, args ...interface{}) (string, error) {
|
||||
return fake.PersonJobtitle(), nil
|
||||
}
|
||||
|
||||
func randCompanyName(ctx context.Context, args ...interface{}) (string, error) {
|
||||
return fake.CompanyName(), nil
|
||||
}
|
||||
|
||||
func randCompanyIndustry(ctx context.Context, args ...interface{}) (string, error) {
|
||||
return fake.CompanyIndustry(), nil
|
||||
}
|
||||
|
||||
func randLocationName(ctx context.Context, args ...interface{}) (string, error) {
|
||||
return fake.LocationName(), nil
|
||||
}
|
||||
|
||||
func randLocationAddress(ctx context.Context, args ...interface{}) (string, error) {
|
||||
return fake.LocationAddress(), nil
|
||||
}
|
||||
|
||||
func randLocationStreet(ctx context.Context, args ...interface{}) (string, error) {
|
||||
return fake.LocationStreet(), nil
|
||||
}
|
||||
|
||||
func randLocationCity(ctx context.Context, args ...interface{}) (string, error) {
|
||||
return fake.LocationCity(), nil
|
||||
}
|
||||
|
||||
func randLocationState(ctx context.Context, args ...interface{}) (string, error) {
|
||||
return fake.LocationState(), nil
|
||||
}
|
||||
|
||||
func randLocationCounty(ctx context.Context, args ...interface{}) (string, error) {
|
||||
return fake.LocationCounty(), nil
|
||||
}
|
||||
|
||||
func randLocationZipcode(ctx context.Context, args ...interface{}) (string, error) {
|
||||
return fake.LocationZipcode(), nil
|
||||
}
|
||||
|
||||
func randLocationPostcode(ctx context.Context, args ...interface{}) (string, error) {
|
||||
return fake.LocationPostcode(), nil
|
||||
}
|
||||
|
||||
func randLocationCountry(ctx context.Context, args ...interface{}) (string, error) {
|
||||
return fake.LocationCountry(), nil
|
||||
}
|
||||
|
||||
func randLocationAltitude(ctx context.Context, args ...interface{}) (float64, error) {
|
||||
return fake.LocationAltitude(), nil
|
||||
}
|
||||
|
||||
func randLocationLatitude(ctx context.Context, args ...interface{}) (float64, error) {
|
||||
return fake.LocationLatitude(), nil
|
||||
}
|
||||
|
||||
func randLocationLongitude(ctx context.Context, args ...interface{}) (float64, error) {
|
||||
return fake.LocationLongitude(), nil
|
||||
}
|
243
util/fncs/rand_test.go
Normal file
243
util/fncs/rand_test.go
Normal file
|
@ -0,0 +1,243 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestRand(t *testing.T) {
|
||||
|
||||
Convey("rand() works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand")
|
||||
So(res, ShouldHaveSameTypeAs, 36.0)
|
||||
})
|
||||
|
||||
Convey("uuid() works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "uuid")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
So(res, ShouldHaveLength, 36)
|
||||
})
|
||||
|
||||
Convey("rand.bool() works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.bool")
|
||||
So(res, ShouldHaveSameTypeAs, true)
|
||||
})
|
||||
|
||||
Convey("rand.uuid() works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.uuid")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
So(res, ShouldHaveLength, 36)
|
||||
})
|
||||
|
||||
Convey("rand.enum() works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.enum")
|
||||
So(res, ShouldHaveSameTypeAs, nil)
|
||||
})
|
||||
|
||||
Convey("rand.enum(a,b,c) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.enum", "one", "two", "tre")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
So(res, ShouldBeIn, []interface{}{"one", "two", "tre"})
|
||||
})
|
||||
|
||||
Convey("rand.time() works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.time")
|
||||
So(res, ShouldHaveSameTypeAs, time.Now())
|
||||
})
|
||||
|
||||
Convey("rand.time(a,b) works properly", t, func() {
|
||||
d, _ := time.ParseDuration("24h")
|
||||
now := time.Now()
|
||||
res, _ := Run(context.Background(), "rand.time", now, now.Add(d))
|
||||
So(res, ShouldHaveSameTypeAs, time.Now())
|
||||
So(res.(time.Time).UnixNano(), ShouldBeBetween, now.UnixNano(), now.Add(d).UnixNano())
|
||||
})
|
||||
|
||||
Convey("rand.string() works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.string")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
})
|
||||
|
||||
Convey("rand.string(a) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.string", int64(12))
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
So(res, ShouldHaveLength, 12)
|
||||
})
|
||||
|
||||
Convey("rand.string(a,b) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.string", int64(12), int64(16))
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
})
|
||||
|
||||
Convey("rand.integer() works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.integer")
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
})
|
||||
|
||||
Convey("rand.integer(a,b) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.integer", int64(12), int64(16))
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
So(res, ShouldBeBetween, 11, 17)
|
||||
})
|
||||
|
||||
Convey("rand.decimal() works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.decimal")
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
})
|
||||
|
||||
Convey("rand.decimal(a,b) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.decimal", int64(12), int64(16))
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
So(res, ShouldBeBetween, 11, 17)
|
||||
})
|
||||
|
||||
Convey("rand.word() works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.word")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
})
|
||||
|
||||
Convey("rand.sentence() works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.sentence")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
})
|
||||
|
||||
Convey("rand.sentence(a,b) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.sentence", int64(12), int64(16))
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
})
|
||||
|
||||
Convey("rand.paragraph() works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.paragraph")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
})
|
||||
|
||||
Convey("rand.paragraph(a,b) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.paragraph", int64(12), int64(16))
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
})
|
||||
|
||||
Convey("rand.person.email works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.person.email")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
So(res, ShouldContainSubstring, "@")
|
||||
})
|
||||
|
||||
Convey("rand.person.phone works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.person.phone")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
So(res, ShouldContainSubstring, " ")
|
||||
})
|
||||
|
||||
Convey("rand.person.fullname works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.person.fullname")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
})
|
||||
|
||||
Convey("rand.person.firstname works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.person.firstname")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
})
|
||||
|
||||
Convey("rand.person.lastname works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.person.lastname")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
})
|
||||
|
||||
Convey("rand.person.username works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.person.username")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
})
|
||||
|
||||
Convey("rand.person.jobtitle works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.person.jobtitle")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
})
|
||||
|
||||
Convey("rand.company.name works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.company.name")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
})
|
||||
|
||||
Convey("rand.company.industry works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.company.industry")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
})
|
||||
|
||||
Convey("rand.location.name works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.location.name")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
})
|
||||
|
||||
Convey("rand.location.address works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.location.address")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
})
|
||||
|
||||
Convey("rand.location.street works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.location.street")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
})
|
||||
|
||||
Convey("rand.location.city works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.location.city")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
})
|
||||
|
||||
Convey("rand.location.state works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.location.state")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
})
|
||||
|
||||
Convey("rand.location.county works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.location.county")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
})
|
||||
|
||||
Convey("rand.location.zipcode works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.location.zipcode")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
})
|
||||
|
||||
Convey("rand.location.postcode works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.location.postcode")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
})
|
||||
|
||||
Convey("rand.location.country works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.location.country")
|
||||
So(res, ShouldHaveSameTypeAs, "test")
|
||||
})
|
||||
|
||||
Convey("rand.location.altitude works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.location.altitude")
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
})
|
||||
|
||||
Convey("rand.location.latitude works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.location.latitude")
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
})
|
||||
|
||||
Convey("rand.location.longitude works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "rand.location.longitude")
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
})
|
||||
|
||||
}
|
40
util/fncs/scrypt.go
Normal file
40
util/fncs/scrypt.go
Normal file
|
@ -0,0 +1,40 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/elithrar/simple-scrypt"
|
||||
)
|
||||
|
||||
func scryptCompare(ctx context.Context, args ...interface{}) (bool, error) {
|
||||
if h, ok := ensureString(args[0]); ok {
|
||||
if s, ok := ensureString(args[1]); ok {
|
||||
e := scrypt.CompareHashAndPassword([]byte(h), []byte(s))
|
||||
if e == nil {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func scryptGenerate(ctx context.Context, args ...interface{}) ([]byte, error) {
|
||||
s, _ := ensureString(args[0])
|
||||
p := []byte(s)
|
||||
o := scrypt.DefaultParams
|
||||
return scrypt.GenerateFromPassword(p, o)
|
||||
}
|
41
util/fncs/scrypt_test.go
Normal file
41
util/fncs/scrypt_test.go
Normal file
|
@ -0,0 +1,41 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestScrypt(t *testing.T) {
|
||||
|
||||
Convey("scrypt.compare(a, b) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "scrypt.compare", "16384$8$1$8065a3ec98903c86d950840721ef945b$1f23d0d2ff5528f033161fd21ce84911f9332ac9878953139ad30b6a8c2959f2", "test")
|
||||
So(res, ShouldEqual, true)
|
||||
})
|
||||
|
||||
Convey("scrypt.compare(a, b) errors properly", t, func() {
|
||||
res, _ := Run(context.Background(), "scrypt.compare", "16384$8$1$8065a3ec98903c86d950840721ef945b$1f23d0d2ff5528f033161fd21ce84911f9332ac9878953139ad30b6a8c2959f2", "wrong")
|
||||
So(res, ShouldEqual, false)
|
||||
})
|
||||
|
||||
Convey("scrypt.generate(a) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "scrypt.generate", "test")
|
||||
So(res, ShouldHaveSameTypeAs, []byte("test"))
|
||||
})
|
||||
|
||||
}
|
104
util/fncs/sets.go
Normal file
104
util/fncs/sets.go
Normal file
|
@ -0,0 +1,104 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
func difference(ctx context.Context, args ...interface{}) ([]interface{}, error) {
|
||||
|
||||
d := make([]interface{}, 0)
|
||||
c := make(map[interface{}]int)
|
||||
|
||||
for _, x := range args {
|
||||
a, _ := ensureSlice(x)
|
||||
for _, v := range a {
|
||||
c[v] += 1
|
||||
}
|
||||
}
|
||||
|
||||
for k, b := range c {
|
||||
if b == 1 {
|
||||
d = append(d, k)
|
||||
}
|
||||
}
|
||||
|
||||
return d, nil
|
||||
|
||||
}
|
||||
|
||||
func distinct(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
|
||||
d := make([]interface{}, 0)
|
||||
c := make(map[interface{}]bool)
|
||||
|
||||
for _, x := range args {
|
||||
a, _ := ensureSlice(x)
|
||||
for _, v := range a {
|
||||
c[v] = true
|
||||
}
|
||||
}
|
||||
|
||||
for k := range c {
|
||||
d = append(d, k)
|
||||
}
|
||||
|
||||
return d, nil
|
||||
|
||||
}
|
||||
|
||||
func intersect(ctx context.Context, args ...interface{}) ([]interface{}, error) {
|
||||
|
||||
l := len(args)
|
||||
d := make([]interface{}, 0)
|
||||
c := make(map[interface{}]int)
|
||||
|
||||
for _, x := range args {
|
||||
a, _ := ensureSlice(x)
|
||||
for _, v := range a {
|
||||
c[v] += 1
|
||||
}
|
||||
}
|
||||
|
||||
for k, b := range c {
|
||||
if b == l {
|
||||
d = append(d, k)
|
||||
}
|
||||
}
|
||||
|
||||
return d, nil
|
||||
|
||||
}
|
||||
|
||||
func union(ctx context.Context, args ...interface{}) ([]interface{}, error) {
|
||||
|
||||
d := make([]interface{}, 0)
|
||||
c := make(map[interface{}]bool)
|
||||
|
||||
for _, x := range args {
|
||||
a, _ := ensureSlice(x)
|
||||
for _, v := range a {
|
||||
c[v] = true
|
||||
}
|
||||
}
|
||||
|
||||
for k := range c {
|
||||
d = append(d, k)
|
||||
}
|
||||
|
||||
return d, nil
|
||||
|
||||
}
|
62
util/fncs/sets_test.go
Normal file
62
util/fncs/sets_test.go
Normal file
|
@ -0,0 +1,62 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestSets(t *testing.T) {
|
||||
|
||||
Convey("difference(a, b, c) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "difference", []interface{}{"one"}, []interface{}{"one", "two"}, []interface{}{"one", "two", "tre"})
|
||||
So(res, ShouldHaveLength, 1)
|
||||
So(res, ShouldContain, "tre")
|
||||
})
|
||||
|
||||
Convey("distinct(a) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "distinct", []interface{}{"one", "two", "two", "tre", "tre", "tre"})
|
||||
So(res, ShouldHaveLength, 3)
|
||||
So(res, ShouldContain, "one")
|
||||
So(res, ShouldContain, "two")
|
||||
So(res, ShouldContain, "tre")
|
||||
})
|
||||
|
||||
Convey("distinct(a, b, c) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "distinct", []interface{}{"one"}, []interface{}{"one", "two"}, []interface{}{"one", "two", "tre"})
|
||||
So(res, ShouldHaveLength, 3)
|
||||
So(res, ShouldContain, "one")
|
||||
So(res, ShouldContain, "two")
|
||||
So(res, ShouldContain, "tre")
|
||||
})
|
||||
|
||||
Convey("intersect(a, b, c) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "intersect", []interface{}{"one"}, []interface{}{"one", "two"}, []interface{}{"one", "two", "tre"})
|
||||
So(res, ShouldHaveLength, 1)
|
||||
So(res, ShouldContain, "one")
|
||||
})
|
||||
|
||||
Convey("union(a, b, c) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "union", []interface{}{"one"}, []interface{}{"one", "two"}, []interface{}{"one", "two", "tre"})
|
||||
So(res, ShouldHaveLength, 3)
|
||||
So(res, ShouldContain, "one")
|
||||
So(res, ShouldContain, "two")
|
||||
So(res, ShouldContain, "tre")
|
||||
})
|
||||
|
||||
}
|
180
util/fncs/string.go
Normal file
180
util/fncs/string.go
Normal file
|
@ -0,0 +1,180 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/abcum/surreal/util/ints"
|
||||
"github.com/abcum/surreal/util/text"
|
||||
)
|
||||
|
||||
func stringConcat(ctx context.Context, args ...interface{}) (str string, err error) {
|
||||
for _, v := range args {
|
||||
str = str + fmt.Sprint(v)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func stringContains(ctx context.Context, args ...interface{}) (bool, error) {
|
||||
s, _ := ensureString(args[0])
|
||||
p, _ := ensureString(args[1])
|
||||
return strings.Contains(s, p), nil
|
||||
}
|
||||
|
||||
func stringEndsWith(ctx context.Context, args ...interface{}) (bool, error) {
|
||||
s, _ := ensureString(args[0])
|
||||
p, _ := ensureString(args[1])
|
||||
return strings.HasSuffix(s, p), nil
|
||||
}
|
||||
|
||||
func stringFormat(ctx context.Context, args ...interface{}) (str string, err error) {
|
||||
switch len(args) {
|
||||
case 0, 1:
|
||||
// Not enough arguments, so just ignore
|
||||
default:
|
||||
s, _ := ensureString(args[0])
|
||||
str = fmt.Sprintf(s, args[1:]...)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func stringIncludes(ctx context.Context, args ...interface{}) (bool, error) {
|
||||
s, _ := ensureString(args[0])
|
||||
p, _ := ensureString(args[1])
|
||||
return strings.Contains(s, p), nil
|
||||
}
|
||||
|
||||
func stringJoin(ctx context.Context, args ...interface{}) (str string, err error) {
|
||||
switch len(args) {
|
||||
case 0, 1:
|
||||
// Not enough arguments, so just ignore
|
||||
default:
|
||||
var a []string
|
||||
j, _ := ensureString(args[0])
|
||||
for _, v := range args[1:] {
|
||||
if v != nil {
|
||||
a = append(a, fmt.Sprint(v))
|
||||
}
|
||||
}
|
||||
str = strings.Join(a, j)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func stringLength(ctx context.Context, args ...interface{}) (float64, error) {
|
||||
s, _ := ensureString(args[0])
|
||||
return float64(len(s)), nil
|
||||
}
|
||||
|
||||
func stringLevenshtein(ctx context.Context, args ...interface{}) (float64, error) {
|
||||
s, _ := ensureString(args[0])
|
||||
c, _ := ensureString(args[1])
|
||||
return float64(text.Levenshtein(s, c)), nil
|
||||
}
|
||||
|
||||
func stringLowercase(ctx context.Context, args ...interface{}) (string, error) {
|
||||
s, _ := ensureString(args[0])
|
||||
return strings.ToLower(s), nil
|
||||
}
|
||||
|
||||
func stringRepeat(ctx context.Context, args ...interface{}) (string, error) {
|
||||
s, _ := ensureString(args[0])
|
||||
if c, ok := ensureInt(args[1]); ok {
|
||||
return strings.Repeat(s, int(c)), nil
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func stringReplace(ctx context.Context, args ...interface{}) (string, error) {
|
||||
s, _ := ensureString(args[0])
|
||||
o, _ := ensureString(args[1])
|
||||
n, _ := ensureString(args[2])
|
||||
return strings.Replace(s, o, n, -1), nil
|
||||
}
|
||||
|
||||
func stringReverse(ctx context.Context, args ...interface{}) (string, error) {
|
||||
s, _ := ensureString(args[0])
|
||||
r := []rune(s)
|
||||
for i, j := 0, len(r)-1; i < j; i, j = i+1, j-1 {
|
||||
r[i], r[j] = r[j], r[i]
|
||||
}
|
||||
return string(r), nil
|
||||
}
|
||||
|
||||
func stringSearch(ctx context.Context, args ...interface{}) (float64, error) {
|
||||
s, _ := ensureString(args[0])
|
||||
p, _ := ensureString(args[1])
|
||||
return float64(strings.Index(s, p)), nil
|
||||
}
|
||||
|
||||
func stringSlice(ctx context.Context, args ...interface{}) (string, error) {
|
||||
s, _ := ensureString(args[0])
|
||||
b, bk := ensureInt(args[1])
|
||||
e, ek := ensureInt(args[2])
|
||||
f := ints.Min(len(s), int(b+e))
|
||||
if bk && ek {
|
||||
return s[b:f], nil
|
||||
} else if bk {
|
||||
return s[b:], nil
|
||||
} else if ek {
|
||||
return s[:f], nil
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func stringSplit(ctx context.Context, args ...interface{}) ([]string, error) {
|
||||
s, _ := ensureString(args[0])
|
||||
p, _ := ensureString(args[1])
|
||||
return strings.Split(s, p), nil
|
||||
}
|
||||
|
||||
func stringStartsWith(ctx context.Context, args ...interface{}) (bool, error) {
|
||||
s, _ := ensureString(args[0])
|
||||
p, _ := ensureString(args[1])
|
||||
return strings.HasPrefix(s, p), nil
|
||||
}
|
||||
|
||||
func stringSubstr(ctx context.Context, args ...interface{}) (string, error) {
|
||||
s, _ := ensureString(args[0])
|
||||
b, bk := ensureInt(args[1])
|
||||
e, ek := ensureInt(args[2])
|
||||
f := ints.Min(len(s), int(e))
|
||||
if bk && ek {
|
||||
return s[b:f], nil
|
||||
} else if bk {
|
||||
return s[b:], nil
|
||||
} else if ek {
|
||||
return s[:f], nil
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func stringTrim(ctx context.Context, args ...interface{}) (string, error) {
|
||||
s, _ := ensureString(args[0])
|
||||
return strings.TrimSpace(s), nil
|
||||
}
|
||||
|
||||
func stringUppercase(ctx context.Context, args ...interface{}) (string, error) {
|
||||
s, _ := ensureString(args[0])
|
||||
return strings.ToUpper(s), nil
|
||||
}
|
||||
|
||||
func stringWords(ctx context.Context, args ...interface{}) ([]string, error) {
|
||||
s, _ := ensureString(args[0])
|
||||
return strings.Fields(s), nil
|
||||
}
|
171
util/fncs/string_test.go
Normal file
171
util/fncs/string_test.go
Normal file
|
@ -0,0 +1,171 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestString(t *testing.T) {
|
||||
|
||||
var res interface{}
|
||||
|
||||
var test = "This IS a test"
|
||||
var spac = " This IS a test "
|
||||
|
||||
Convey("string.concat() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "string.concat", nil, 1, 1.5, "2", true, false)
|
||||
So(res, ShouldEqual, "<nil>11.52truefalse")
|
||||
})
|
||||
|
||||
Convey("string.contains() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "string.contains", test, "done")
|
||||
So(res, ShouldEqual, false)
|
||||
res, _ = Run(context.Background(), "string.contains", test, "test")
|
||||
So(res, ShouldEqual, true)
|
||||
})
|
||||
|
||||
Convey("string.endsWith() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "string.endsWith", test, "done")
|
||||
So(res, ShouldEqual, false)
|
||||
res, _ = Run(context.Background(), "string.endsWith", test, "test")
|
||||
So(res, ShouldEqual, true)
|
||||
})
|
||||
|
||||
Convey("string.format() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "string.format", "%.9d", 1)
|
||||
So(res, ShouldEqual, "000000001")
|
||||
})
|
||||
|
||||
Convey("string.format() errors properly", t, func() {
|
||||
res, _ = Run(context.Background(), "string.format", "%.9d")
|
||||
So(res, ShouldEqual, "")
|
||||
})
|
||||
|
||||
Convey("string.includes() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "string.includes", test, "done")
|
||||
So(res, ShouldEqual, false)
|
||||
res, _ = Run(context.Background(), "string.includes", test, "test")
|
||||
So(res, ShouldEqual, true)
|
||||
})
|
||||
|
||||
Convey("string.join() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "string.join")
|
||||
So(res, ShouldEqual, "")
|
||||
res, _ = Run(context.Background(), "string.join", ",")
|
||||
So(res, ShouldEqual, "")
|
||||
res, _ = Run(context.Background(), "string.join", ",", nil, 1, 1.5, "2", true, false)
|
||||
So(res, ShouldEqual, "1,1.5,2,true,false")
|
||||
})
|
||||
|
||||
Convey("string.length() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "string.length", test)
|
||||
So(res, ShouldEqual, 14)
|
||||
})
|
||||
|
||||
Convey("string.levenshtein() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "string.levenshtein", "test", "test")
|
||||
So(res, ShouldEqual, 0)
|
||||
res, _ = Run(context.Background(), "string.levenshtein", "lawn", "flaw")
|
||||
So(res, ShouldEqual, 2)
|
||||
res, _ = Run(context.Background(), "string.levenshtein", "test", "done")
|
||||
So(res, ShouldEqual, 4)
|
||||
})
|
||||
|
||||
Convey("string.lowercase() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "string.lowercase", test)
|
||||
So(res, ShouldEqual, "this is a test")
|
||||
})
|
||||
|
||||
Convey("string.repeat(a, b) works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "string.repeat", test, 2)
|
||||
So(res, ShouldEqual, test+test)
|
||||
})
|
||||
|
||||
Convey("string.repeat(a, b) errors properly", t, func() {
|
||||
res, _ = Run(context.Background(), "string.repeat", test, "test")
|
||||
So(res, ShouldEqual, test)
|
||||
})
|
||||
|
||||
Convey("string.replace() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "string.replace", test, "test", "note")
|
||||
So(res, ShouldEqual, "This IS a note")
|
||||
})
|
||||
|
||||
Convey("string.reverse() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "string.reverse", test, "test")
|
||||
So(res, ShouldEqual, "tset a SI sihT")
|
||||
})
|
||||
|
||||
Convey("string.search() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "string.search", test, "done")
|
||||
So(res, ShouldEqual, -1)
|
||||
res, _ = Run(context.Background(), "string.search", test, "test")
|
||||
So(res, ShouldEqual, 10)
|
||||
})
|
||||
|
||||
Convey("string.slice() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "string.slice", test, "a", "b")
|
||||
So(res, ShouldEqual, test)
|
||||
res, _ = Run(context.Background(), "string.slice", test, "2", "b")
|
||||
So(res, ShouldEqual, test[2:])
|
||||
res, _ = Run(context.Background(), "string.slice", test, "a", "2")
|
||||
So(res, ShouldEqual, test[:2])
|
||||
res, _ = Run(context.Background(), "string.slice", test, "2", "4")
|
||||
So(res, ShouldEqual, test[2:4+2])
|
||||
})
|
||||
|
||||
Convey("string.split() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "string.split", test, " ")
|
||||
So(res, ShouldResemble, []string{"This", "IS", "a", "test"})
|
||||
})
|
||||
|
||||
Convey("string.startsWith() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "string.startsWith", test, "this")
|
||||
So(res, ShouldEqual, false)
|
||||
res, _ = Run(context.Background(), "string.startsWith", test, "This")
|
||||
So(res, ShouldEqual, true)
|
||||
})
|
||||
|
||||
Convey("string.substr() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "string.substr", test, "a", "b")
|
||||
So(res, ShouldEqual, test)
|
||||
res, _ = Run(context.Background(), "string.substr", test, "2", "b")
|
||||
So(res, ShouldEqual, test[2:])
|
||||
res, _ = Run(context.Background(), "string.substr", test, "a", "2")
|
||||
So(res, ShouldEqual, test[:2])
|
||||
res, _ = Run(context.Background(), "string.substr", test, "2", "4")
|
||||
So(res, ShouldEqual, test[2:4])
|
||||
})
|
||||
|
||||
Convey("string.trim() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "string.trim", spac)
|
||||
So(res, ShouldEqual, test)
|
||||
})
|
||||
|
||||
Convey("string.uppercase() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "string.uppercase", test)
|
||||
So(res, ShouldEqual, "THIS IS A TEST")
|
||||
})
|
||||
|
||||
Convey("string.words() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "string.words", test)
|
||||
So(res, ShouldResemble, []string{"This", "IS", "a", "test"})
|
||||
})
|
||||
|
||||
}
|
26
util/fncs/table.go
Normal file
26
util/fncs/table.go
Normal file
|
@ -0,0 +1,26 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/abcum/surreal/sql"
|
||||
)
|
||||
|
||||
func table(ctx context.Context, args ...interface{}) (*sql.Table, error) {
|
||||
tb, _ := ensureString(args[0])
|
||||
return sql.NewTable(tb), nil
|
||||
}
|
36
util/fncs/table_test.go
Normal file
36
util/fncs/table_test.go
Normal file
|
@ -0,0 +1,36 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/abcum/surreal/sql"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestTable(t *testing.T) {
|
||||
|
||||
var res interface{}
|
||||
|
||||
Convey("table() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "table", 1)
|
||||
So(res, ShouldResemble, sql.NewTable("1"))
|
||||
res, _ = Run(context.Background(), "table", "test")
|
||||
So(res, ShouldResemble, sql.NewTable("test"))
|
||||
})
|
||||
|
||||
}
|
26
util/fncs/thing.go
Normal file
26
util/fncs/thing.go
Normal file
|
@ -0,0 +1,26 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/abcum/surreal/sql"
|
||||
)
|
||||
|
||||
func thing(ctx context.Context, args ...interface{}) (*sql.Thing, error) {
|
||||
tb, _ := ensureString(args[0])
|
||||
return sql.NewThing(tb, args[1]), nil
|
||||
}
|
36
util/fncs/thing_test.go
Normal file
36
util/fncs/thing_test.go
Normal file
|
@ -0,0 +1,36 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/abcum/surreal/sql"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestThing(t *testing.T) {
|
||||
|
||||
var res interface{}
|
||||
|
||||
Convey("thing() works properly", t, func() {
|
||||
res, _ = Run(context.Background(), "thing", 1, 1)
|
||||
So(res, ShouldResemble, sql.NewThing("1", 1))
|
||||
res, _ = Run(context.Background(), "thing", "test", 1)
|
||||
So(res, ShouldResemble, sql.NewThing("test", 1))
|
||||
})
|
||||
|
||||
}
|
156
util/fncs/time.go
Normal file
156
util/fncs/time.go
Normal file
|
@ -0,0 +1,156 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
func timeNow(ctx context.Context, args ...interface{}) (time.Time, error) {
|
||||
return time.Now(), nil
|
||||
}
|
||||
|
||||
func timeAdd(ctx context.Context, args ...interface{}) (time.Time, error) {
|
||||
if t, ok := ensureTime(args[0]); ok {
|
||||
if d, ok := ensureDuration(args[1]); ok {
|
||||
return t.Add(d), nil
|
||||
}
|
||||
}
|
||||
return time.Unix(0, 0), nil
|
||||
}
|
||||
|
||||
func timeAge(ctx context.Context, args ...interface{}) (time.Time, error) {
|
||||
if t, ok := ensureTime(args[0]); ok {
|
||||
if d, ok := ensureDuration(args[1]); ok {
|
||||
return t.Add(-d), nil
|
||||
}
|
||||
}
|
||||
return time.Unix(0, 0), nil
|
||||
}
|
||||
|
||||
func timeFloor(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
if t, ok := ensureTime(args[0]); ok {
|
||||
if d, ok := ensureDuration(args[1]); ok {
|
||||
return t.Truncate(d), nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func timeRound(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||
if t, ok := ensureTime(args[0]); ok {
|
||||
if d, ok := ensureDuration(args[1]); ok {
|
||||
return t.Round(d), nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func timeDay(ctx context.Context, args ...interface{}) (float64, error) {
|
||||
switch len(args) {
|
||||
case 0:
|
||||
return float64(time.Now().Day()), nil
|
||||
case 1:
|
||||
if v, ok := ensureTime(args[0]); ok {
|
||||
return float64(v.Day()), nil
|
||||
}
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func timeHour(ctx context.Context, args ...interface{}) (float64, error) {
|
||||
switch len(args) {
|
||||
case 0:
|
||||
return float64(time.Now().Hour()), nil
|
||||
case 1:
|
||||
if v, ok := ensureTime(args[0]); ok {
|
||||
return float64(v.Hour()), nil
|
||||
}
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func timeMins(ctx context.Context, args ...interface{}) (float64, error) {
|
||||
switch len(args) {
|
||||
case 0:
|
||||
return float64(time.Now().Minute()), nil
|
||||
case 1:
|
||||
if v, ok := ensureTime(args[0]); ok {
|
||||
return float64(v.Minute()), nil
|
||||
}
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func timeMonth(ctx context.Context, args ...interface{}) (float64, error) {
|
||||
switch len(args) {
|
||||
case 0:
|
||||
return float64(time.Now().Month()), nil
|
||||
case 1:
|
||||
if v, ok := ensureTime(args[0]); ok {
|
||||
return float64(v.Month()), nil
|
||||
}
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func timeNano(ctx context.Context, args ...interface{}) (float64, error) {
|
||||
switch len(args) {
|
||||
case 0:
|
||||
return float64(time.Now().UnixNano()), nil
|
||||
case 1:
|
||||
if v, ok := ensureTime(args[0]); ok {
|
||||
return float64(v.UnixNano()), nil
|
||||
}
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func timeSecs(ctx context.Context, args ...interface{}) (float64, error) {
|
||||
switch len(args) {
|
||||
case 0:
|
||||
return float64(time.Now().Second()), nil
|
||||
case 1:
|
||||
if v, ok := ensureTime(args[0]); ok {
|
||||
return float64(v.Second()), nil
|
||||
}
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func timeUnix(ctx context.Context, args ...interface{}) (float64, error) {
|
||||
switch len(args) {
|
||||
case 0:
|
||||
return float64(time.Now().Unix()), nil
|
||||
case 1:
|
||||
if v, ok := ensureTime(args[0]); ok {
|
||||
return float64(v.Unix()), nil
|
||||
}
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func timeYear(ctx context.Context, args ...interface{}) (float64, error) {
|
||||
switch len(args) {
|
||||
case 0:
|
||||
return float64(time.Now().Year()), nil
|
||||
case 1:
|
||||
if v, ok := ensureTime(args[0]); ok {
|
||||
return float64(v.Year()), nil
|
||||
}
|
||||
}
|
||||
return 0, nil
|
||||
}
|
234
util/fncs/time_test.go
Normal file
234
util/fncs/time_test.go
Normal file
|
@ -0,0 +1,234 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// 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 fncs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestTime(t *testing.T) {
|
||||
|
||||
now := time.Now()
|
||||
org := time.Unix(0, 0)
|
||||
dur := 24 * time.Hour
|
||||
old, _ := time.Parse(time.RFC822Z, time.RFC822Z)
|
||||
old = old.UTC()
|
||||
rnd, _ := time.Parse("2006-01-02", "2006-01-03")
|
||||
rnd = rnd.UTC()
|
||||
trc, _ := time.Parse("2006-01-02", "2006-01-02")
|
||||
trc = trc.UTC()
|
||||
|
||||
Convey("time.now() works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.now")
|
||||
So(res, ShouldHaveSameTypeAs, now)
|
||||
})
|
||||
|
||||
Convey("time.add(a, b) works properly", t, func() {
|
||||
dur, _ := time.ParseDuration("1h")
|
||||
res, _ := Run(context.Background(), "time.add", now, dur)
|
||||
So(res, ShouldHaveSameTypeAs, now)
|
||||
So(res, ShouldHappenAfter, now)
|
||||
})
|
||||
|
||||
Convey("time.add(a, b) errors properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.add", now, nil)
|
||||
So(res, ShouldHaveSameTypeAs, org)
|
||||
So(res, ShouldEqual, org)
|
||||
})
|
||||
|
||||
Convey("time.age(a, b) errors properly", t, func() {
|
||||
dur, _ := time.ParseDuration("1h")
|
||||
res, _ := Run(context.Background(), "time.age", now, dur)
|
||||
So(res, ShouldHaveSameTypeAs, now)
|
||||
So(res, ShouldHappenBefore, now)
|
||||
})
|
||||
|
||||
Convey("time.age(a, b) errors properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.age", now, nil)
|
||||
So(res, ShouldHaveSameTypeAs, org)
|
||||
So(res, ShouldEqual, org)
|
||||
})
|
||||
|
||||
Convey("time.floor(a,b) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.floor", old, dur)
|
||||
So(res, ShouldHaveSameTypeAs, org)
|
||||
So(res, ShouldEqual, trc)
|
||||
})
|
||||
|
||||
Convey("time.floor(a,b) errors properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.floor", "one", "two")
|
||||
So(res, ShouldEqual, nil)
|
||||
})
|
||||
|
||||
Convey("time.round(a,b) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.round", old, dur)
|
||||
So(res, ShouldHaveSameTypeAs, org)
|
||||
So(res, ShouldEqual, rnd)
|
||||
})
|
||||
|
||||
Convey("time.round(a,b) errors properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.round", "one", "two")
|
||||
So(res, ShouldEqual, nil)
|
||||
})
|
||||
|
||||
Convey("time.day() works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.day")
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
So(res, ShouldEqual, now.Day())
|
||||
})
|
||||
|
||||
Convey("time.day(a) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.day", old)
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
So(res, ShouldEqual, 2)
|
||||
})
|
||||
|
||||
Convey("time.day(a,b,c) errors properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.day", "one", "two")
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
So(res, ShouldEqual, 0)
|
||||
})
|
||||
|
||||
Convey("time.hour() works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.hour")
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
So(res, ShouldEqual, now.Hour())
|
||||
})
|
||||
|
||||
Convey("time.hour(a) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.hour", old)
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
So(res, ShouldEqual, 22)
|
||||
})
|
||||
|
||||
Convey("time.hour(a,b,c) errors properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.hour", "one", "two")
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
So(res, ShouldEqual, 0)
|
||||
})
|
||||
|
||||
Convey("time.mins() works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.mins")
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
So(res, ShouldEqual, now.Minute())
|
||||
})
|
||||
|
||||
Convey("time.mins(a) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.mins", old)
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
So(res, ShouldEqual, 4)
|
||||
})
|
||||
|
||||
Convey("time.mins(a,b,c) errors properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.mins", "one", "two")
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
So(res, ShouldEqual, 0)
|
||||
})
|
||||
|
||||
Convey("time.month() works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.month")
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
So(res, ShouldEqual, now.Month())
|
||||
})
|
||||
|
||||
Convey("time.month(a) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.month", old)
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
So(res, ShouldEqual, 1)
|
||||
})
|
||||
|
||||
Convey("time.month(a,b,c) errors properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.month", "one", "two")
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
So(res, ShouldEqual, 0)
|
||||
})
|
||||
|
||||
Convey("time.nano() works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.nano")
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
So(res, ShouldBeGreaterThanOrEqualTo, now.UnixNano())
|
||||
})
|
||||
|
||||
Convey("time.nano(a) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.nano", old)
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
So(res, ShouldEqual, 1136239440000000000)
|
||||
})
|
||||
|
||||
Convey("time.nano(a,b,c) errors properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.nano", "one", "two")
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
So(res, ShouldEqual, 0)
|
||||
})
|
||||
|
||||
Convey("time.secs() works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.secs")
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
So(res, ShouldEqual, now.Second())
|
||||
})
|
||||
|
||||
Convey("time.secs(a) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.secs", old)
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
So(res, ShouldEqual, 0)
|
||||
})
|
||||
|
||||
Convey("time.secs(a,b,c) errors properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.secs", "one", "two")
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
So(res, ShouldEqual, 0)
|
||||
})
|
||||
|
||||
Convey("time.unix() works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.unix")
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
So(res, ShouldBeGreaterThanOrEqualTo, now.Unix())
|
||||
})
|
||||
|
||||
Convey("time.unix(a) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.unix", old)
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
So(res, ShouldEqual, 1136239440)
|
||||
})
|
||||
|
||||
Convey("time.unix(a,b,c) errors properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.unix", "one", "two")
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
So(res, ShouldEqual, 0)
|
||||
})
|
||||
|
||||
Convey("time.year() works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.year")
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
So(res, ShouldEqual, now.Year())
|
||||
})
|
||||
|
||||
Convey("time.year(a) works properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.year", old)
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
So(res, ShouldEqual, 2006)
|
||||
})
|
||||
|
||||
Convey("time.year(a,b,c) errors properly", t, func() {
|
||||
res, _ := Run(context.Background(), "time.year", "one", "two")
|
||||
So(res, ShouldHaveSameTypeAs, float64(0))
|
||||
So(res, ShouldEqual, 0)
|
||||
})
|
||||
|
||||
}
|
Loading…
Reference in a new issue