1// Copyright 2011 Aaron Jacobs. All Rights Reserved. 2// Author: aaronjjacobs@gmail.com (Aaron Jacobs) 3// 4// Licensed under the Apache License, Version 2.0 (the "License"); 5// you may not use this file except in compliance with the License. 6// You may obtain a copy of the License at 7// 8// http://www.apache.org/licenses/LICENSE-2.0 9// 10// Unless required by applicable law or agreed to in writing, software 11// distributed under the License is distributed on an "AS IS" BASIS, 12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13// See the License for the specific language governing permissions and 14// limitations under the License. 15 16package ogletest 17 18import ( 19 "fmt" 20 "path" 21 "reflect" 22 "runtime" 23 24 "github.com/smartystreets/assertions/internal/oglematchers" 25) 26 27// ExpectThat confirms that the supplied matcher matches the value x, adding a 28// failure record to the currently running test if it does not. If additional 29// parameters are supplied, the first will be used as a format string for the 30// later ones, and the user-supplied error message will be added to the test 31// output in the event of a failure. 32// 33// For example: 34// 35// ExpectThat(userName, Equals("jacobsa")) 36// ExpectThat(users[i], Equals("jacobsa"), "while processing user %d", i) 37// 38func ExpectThat( 39 x interface{}, 40 m oglematchers.Matcher, 41 errorParts ...interface{}) { 42 expectThat(x, m, 1, errorParts) 43} 44 45// The generalized form of ExpectThat. depth is the distance on the stack 46// between the caller's frame and the user's frame. Returns passed iff the 47// match succeeded. 48func expectThat( 49 x interface{}, 50 m oglematchers.Matcher, 51 depth int, 52 errorParts []interface{}) (passed bool) { 53 // Check whether the value matches. If it does, we are finished. 54 matcherErr := m.Matches(x) 55 if matcherErr == nil { 56 passed = true 57 return 58 } 59 60 var r FailureRecord 61 62 // Get information about the call site. 63 var ok bool 64 if _, r.FileName, r.LineNumber, ok = runtime.Caller(depth + 1); !ok { 65 panic("expectThat: runtime.Caller") 66 } 67 68 r.FileName = path.Base(r.FileName) 69 70 // Create an appropriate failure message. Make sure that the expected and 71 // actual values align properly. 72 relativeClause := "" 73 if matcherErr.Error() != "" { 74 relativeClause = fmt.Sprintf(", %s", matcherErr.Error()) 75 } 76 77 r.Error = fmt.Sprintf( 78 "Expected: %s\nActual: %v%s", 79 m.Description(), 80 x, 81 relativeClause) 82 83 // Add the user error, if any. 84 if len(errorParts) != 0 { 85 v := reflect.ValueOf(errorParts[0]) 86 if v.Kind() != reflect.String { 87 panic(fmt.Sprintf("ExpectThat: invalid format string type %v", v.Kind())) 88 } 89 90 r.Error = fmt.Sprintf( 91 "%s\n%s", 92 r.Error, 93 fmt.Sprintf(v.String(), errorParts[1:]...)) 94 } 95 96 // Report the failure. 97 AddFailureRecord(r) 98 99 return 100} 101