mirror of https://github.com/gogits/gogs.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
91 lines
2.5 KiB
91 lines
2.5 KiB
// Copyright 2012 Aaron Jacobs. All Rights Reserved. |
|
// Author: aaronjjacobs@gmail.com (Aaron Jacobs) |
|
// |
|
// 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 oglematchers |
|
|
|
import ( |
|
"errors" |
|
"fmt" |
|
"reflect" |
|
"strings" |
|
) |
|
|
|
// Given a list of arguments M, ElementsAre returns a matcher that matches |
|
// arrays and slices A where all of the following hold: |
|
// |
|
// * A is the same length as M. |
|
// |
|
// * For each i < len(A) where M[i] is a matcher, A[i] matches M[i]. |
|
// |
|
// * For each i < len(A) where M[i] is not a matcher, A[i] matches |
|
// Equals(M[i]). |
|
// |
|
func ElementsAre(M ...interface{}) Matcher { |
|
// Copy over matchers, or convert to Equals(x) for non-matcher x. |
|
subMatchers := make([]Matcher, len(M)) |
|
for i, x := range M { |
|
if matcher, ok := x.(Matcher); ok { |
|
subMatchers[i] = matcher |
|
continue |
|
} |
|
|
|
subMatchers[i] = Equals(x) |
|
} |
|
|
|
return &elementsAreMatcher{subMatchers} |
|
} |
|
|
|
type elementsAreMatcher struct { |
|
subMatchers []Matcher |
|
} |
|
|
|
func (m *elementsAreMatcher) Description() string { |
|
subDescs := make([]string, len(m.subMatchers)) |
|
for i, sm := range m.subMatchers { |
|
subDescs[i] = sm.Description() |
|
} |
|
|
|
return fmt.Sprintf("elements are: [%s]", strings.Join(subDescs, ", ")) |
|
} |
|
|
|
func (m *elementsAreMatcher) Matches(candidates interface{}) error { |
|
// The candidate must be a slice or an array. |
|
v := reflect.ValueOf(candidates) |
|
if v.Kind() != reflect.Slice && v.Kind() != reflect.Array { |
|
return NewFatalError("which is not a slice or array") |
|
} |
|
|
|
// The length must be correct. |
|
if v.Len() != len(m.subMatchers) { |
|
return errors.New(fmt.Sprintf("which is of length %d", v.Len())) |
|
} |
|
|
|
// Check each element. |
|
for i, subMatcher := range m.subMatchers { |
|
c := v.Index(i) |
|
if matchErr := subMatcher.Matches(c.Interface()); matchErr != nil { |
|
// Return an errors indicating which element doesn't match. If the |
|
// matcher error was fatal, make this one fatal too. |
|
err := errors.New(fmt.Sprintf("whose element %d doesn't match", i)) |
|
if _, isFatal := matchErr.(*FatalError); isFatal { |
|
err = NewFatalError(err.Error()) |
|
} |
|
|
|
return err |
|
} |
|
} |
|
|
|
return nil |
|
}
|
|
|