mirror of
https://github.com/go-vgo/robotgo.git
synced 2025-06-03 07:33:55 +00:00
288 lines
6.4 KiB
Go
288 lines
6.4 KiB
Go
// Copyright 2018 The go-ego Project Developers.
|
|
//
|
|
// 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 tt is simple and colorful test tools
|
|
|
|
package tt
|
|
|
|
import (
|
|
"fmt"
|
|
"runtime"
|
|
"strings"
|
|
"testing"
|
|
"unicode"
|
|
"unicode/utf8"
|
|
)
|
|
|
|
// TestingT is an interface wrapper around *testing.T
|
|
type TestingT interface {
|
|
Errorf(format string, args ...interface{})
|
|
}
|
|
|
|
// Blue returns a blue string
|
|
func Blue(message string) string {
|
|
return fmt.Sprintf("\x1b[34m%s\x1b[0m", message)
|
|
}
|
|
|
|
// Red returns a red string
|
|
func Red(message string) string {
|
|
return fmt.Sprintf("\x1b[31m%s\x1b[0m", message)
|
|
}
|
|
|
|
// Yellow returns a yellow string
|
|
func Yellow(message string) string {
|
|
return fmt.Sprintf("\x1b[33m%s\x1b[0m", message)
|
|
}
|
|
|
|
//Bold returns a blod string
|
|
func Bold(message string) string {
|
|
return fmt.Sprintf("\x1b[1m%s\x1b[21m", message)
|
|
}
|
|
|
|
// RedBold returns a red bold string
|
|
func RedBold(message string) string {
|
|
return fmt.Sprintf("\x1b[31m%s\x1b[0m", Bold(message))
|
|
}
|
|
|
|
func isTest(name, prefix string) bool {
|
|
if !strings.HasPrefix(name, prefix) {
|
|
return false
|
|
}
|
|
if len(name) == len(prefix) { // "Test" is ok
|
|
return true
|
|
}
|
|
rune, _ := utf8.DecodeRuneInString(name[len(prefix):])
|
|
return !unicode.IsLower(rune)
|
|
}
|
|
|
|
// CallerInfo returns an array of strings containing the file and line number
|
|
// of each stack frame leading from the current test to the assert call that
|
|
// failed.
|
|
func CallerInfo() []string {
|
|
|
|
pc := uintptr(0)
|
|
file := ""
|
|
line := 0
|
|
ok := false
|
|
name := ""
|
|
|
|
callers := []string{}
|
|
for i := 0; ; i++ {
|
|
pc, file, line, ok = runtime.Caller(i)
|
|
if !ok {
|
|
// The breaks below failed to terminate the loop, and we ran off the
|
|
// end of the call stack.
|
|
break
|
|
}
|
|
|
|
// This is a huge edge case, but it will panic if this is the case, see #180
|
|
if file == "<autogenerated>" {
|
|
break
|
|
}
|
|
|
|
f := runtime.FuncForPC(pc)
|
|
if f == nil {
|
|
break
|
|
}
|
|
name = f.Name()
|
|
|
|
// testing.tRunner is the standard library function that calls
|
|
// tests. Subtests are called directly by tRunner, without going through
|
|
// the Test/Benchmark/Example function that contains the t.Run calls, so
|
|
// with subtests we should break when we hit tRunner, without adding it
|
|
// to the list of callers.
|
|
if name == "testing.tRunner" {
|
|
break
|
|
}
|
|
|
|
parts := strings.Split(file, "/")
|
|
file = parts[len(parts)-1]
|
|
if len(parts) > 1 {
|
|
dir := parts[len(parts)-2]
|
|
if (dir != "assert" && dir != "mock" && dir != "require") ||
|
|
file == "mock_test.go" {
|
|
callers = append(callers, fmt.Sprintf("%s:%d", file, line))
|
|
}
|
|
}
|
|
|
|
// Drop the package
|
|
segments := strings.Split(name, ".")
|
|
name = segments[len(segments)-1]
|
|
if isTest(name, "Test") ||
|
|
isTest(name, "Benchmark") ||
|
|
isTest(name, "Example") {
|
|
break
|
|
}
|
|
}
|
|
|
|
return callers
|
|
}
|
|
|
|
// BM func Benchmark1(b *testing.B, fn func())
|
|
func BM(b *testing.B, fn func()) {
|
|
for i := 0; i < b.N; i++ {
|
|
fn()
|
|
}
|
|
}
|
|
|
|
// FmtErr return error string
|
|
func FmtErr(call int) string {
|
|
err := RedBold("\n Error Trace: " + CallerInfo()[call] + ",")
|
|
err += Yellow("\n Error: Not equal; \n ")
|
|
err += Blue("expected: '%s',\n ") + Red("but got: '%s' \n\n")
|
|
return err
|
|
}
|
|
|
|
// Equal asserts that two objects are equal.
|
|
//
|
|
// tt.Equal(t *testing.T, 1, 1)
|
|
//
|
|
func Equal(t TestingT, expect, actual interface{}, args ...int) bool {
|
|
call := 4
|
|
if len(args) > 0 {
|
|
call = args[0]
|
|
}
|
|
|
|
expectStr := fmt.Sprint(expect)
|
|
return Expect(t, expectStr, actual, call)
|
|
}
|
|
|
|
// Expect asserts that string and objects are equal.
|
|
//
|
|
// tt.Expect(t *testing.T, "1", 1)
|
|
//
|
|
func Expect(t TestingT, expect string, actual interface{}, args ...int) bool {
|
|
call := 3
|
|
if len(args) > 0 {
|
|
call = args[0]
|
|
}
|
|
|
|
actualStr := fmt.Sprint(actual)
|
|
if expect != actualStr {
|
|
err := FmtErr(call)
|
|
t.Errorf(err, expect, actualStr)
|
|
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
// Nil asserts that nil and objects are equal.
|
|
func Nil(t TestingT, actual interface{}, args ...int) bool {
|
|
call := 4
|
|
if len(args) > 0 {
|
|
call = args[0]
|
|
}
|
|
|
|
return Expect(t, "<nil>", actual, call)
|
|
}
|
|
|
|
// Empty asserts that empty and objects are equal.
|
|
func Empty(t TestingT, actual interface{}, args ...int) bool {
|
|
call := 4
|
|
if len(args) > 0 {
|
|
call = args[0]
|
|
}
|
|
|
|
return Expect(t, "", actual, call)
|
|
}
|
|
|
|
// Bool asserts that true and objects are equal.
|
|
func Bool(t TestingT, actual interface{}, args ...int) bool {
|
|
call := 4
|
|
if len(args) > 0 {
|
|
call = args[0]
|
|
}
|
|
|
|
return Expect(t, "true", actual, call)
|
|
}
|
|
|
|
// True asserts that true and objects are equal.
|
|
func True(t TestingT, actual interface{}, args ...int) bool {
|
|
call := 4
|
|
if len(args) > 0 {
|
|
call = args[0]
|
|
}
|
|
|
|
return Expect(t, "true", actual, call)
|
|
}
|
|
|
|
// False asserts that flase and objects are equal.
|
|
func False(t TestingT, actual interface{}, args ...int) bool {
|
|
call := 4
|
|
if len(args) > 0 {
|
|
call = args[0]
|
|
}
|
|
|
|
return Expect(t, "false", actual, call)
|
|
}
|
|
|
|
// NotErr return not equal error string
|
|
func NotErr(call int) string {
|
|
err := RedBold("\n Error Trace: " + CallerInfo()[call] + ",")
|
|
err += Yellow("\n Error: Equal; \n ")
|
|
err += Blue("not expected: '%s',\n ") + Red("but got: '%s' \n\n")
|
|
return err
|
|
}
|
|
|
|
// Not asserts that two objects are not equal.
|
|
//
|
|
// tt.NotEqual(t *testing.T, 1, 1)
|
|
//
|
|
func Not(t TestingT, expect, actual interface{}, args ...int) bool {
|
|
call := 4
|
|
if len(args) > 0 {
|
|
call = args[0]
|
|
}
|
|
|
|
expectStr := fmt.Sprint(expect)
|
|
return NotExpect(t, expectStr, actual, call)
|
|
}
|
|
|
|
// NotEqual asserts that two objects are not equal.
|
|
//
|
|
// tt.NotEqual(t *testing.T, 1, 1)
|
|
//
|
|
func NotEqual(t TestingT, expect, actual interface{}, args ...int) bool {
|
|
call := 4
|
|
if len(args) > 0 {
|
|
call = args[0]
|
|
}
|
|
|
|
expectStr := fmt.Sprint(expect)
|
|
return NotExpect(t, expectStr, actual, call)
|
|
}
|
|
|
|
// NotExpect asserts that string and objects are not equal.
|
|
//
|
|
// tt.NotExpect(t *testing.T, "1", 1)
|
|
//
|
|
func NotExpect(t TestingT, expect string, actual interface{}, args ...int) bool {
|
|
call := 3
|
|
if len(args) > 0 {
|
|
call = args[0]
|
|
}
|
|
|
|
actualStr := fmt.Sprint(actual)
|
|
if expect == actualStr {
|
|
err := NotErr(call)
|
|
t.Errorf(err, expect, actualStr)
|
|
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|