blob: 5347de433081517068632555f5688ccb9e039ee1 [file] [log] [blame]
// Copyright (C) 2016 The Android Open Source Project
//
// 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 assert
import (
"fmt"
"time"
"android.googlesource.com/platform/tools/gpu/framework/log"
)
const (
expected = "Got: %+v\nExpected: %+v"
unmatched = "Got: %+v\n%s: %+v"
)
// Assertion is the type for the start of an assertion line.
// You construct an assertion from a context using either assert.With or assert.For.
type Assertion struct {
ctx log.Context
message string
}
// For start an assertion with the supplied context and message.
// This should be followed by a subject and test calls.
func For(ctx log.Context, message string, args ...interface{}) Assertion {
if len(args) > 0 {
message = fmt.Sprintf(message, args...)
}
return Assertion{
ctx: ctx,
message: message,
}
}
// With starts an assertion with a context but no message.
func With(ctx log.Context) Assertion {
return Assertion{
ctx: ctx,
message: "",
}
}
// Critical returns an Assertion handler that asserts at critical level.
// This will cause the test to immediately fail.
func (a Assertion) Critical() Assertion {
a.ctx = a.ctx.Severity(log.CriticalLevel)
return a
}
// That returns an OnValue for the specified untyped value.
func (a Assertion) That(value interface{}) OnValue {
return OnValue{Assertion: a, value: value}
}
// ThatString returns an OnString for string based assertions.
// The untyped argument is converted to a string using fmt.Sprint, and the result supports string specific tests.
func (a Assertion) ThatString(value interface{}) OnString {
on := OnString{Assertion: a}
switch v := value.(type) {
case string:
on.value = v
case []byte:
on.value = string(v)
default:
on.value = fmt.Sprint(value)
}
return on
}
// ThatError returns an OnError for error type assertions.
func (a Assertion) ThatError(err error) OnError {
return OnError{Assertion: a, err: err}
}
// ThatInteger returns an OnInteger for integer based assertions.
func (a Assertion) ThatInteger(value int) OnInteger {
return OnInteger{Assertion: a, value: value}
}
// ThatFloat returns an OnFloat for floating point based assertions.
func (a Assertion) ThatFloat(value float64) OnFloat {
return OnFloat{Assertion: a, value: value}
}
// ThatDuration returns an OnDuration for time duration based assertions.
func (a Assertion) ThatDuration(value time.Duration) OnDuration {
return OnDuration{Assertion: a, value: value}
}
// ThatSlice returns an OnSlice for assertions on slice type objects.
// Calling this with a non slice type will result in panics.
func (a Assertion) ThatSlice(slice interface{}) OnSlice {
return OnSlice{Assertion: a, slice: slice}
}
// ThatEnum returns an OnEnum for assertions on enumeration objects.
func (a Assertion) ThatEnum(enum Enum) OnEnum {
return OnEnum{Assertion: a, enum: enum}
}
func (a Assertion) logger() log.Logger {
severity, ok := a.ctx.Value(log.SeverityKey).(log.Severity)
if !ok {
severity = log.ErrorLevel
}
return a.ctx.At(severity)
}
func (a Assertion) emit(detail string) {
a.logger().Detail(detail).Log(a.message)
}
func (a Assertion) emitf(detail string, args ...interface{}) {
a.logger().Detail(fmt.Sprintf(detail, args...)).Log(a.message)
}
func (a Assertion) test(condition bool, detail string, args ...interface{}) bool {
if !condition {
a.emitf(detail, args...)
}
return condition
}