prometheus/tsdb/errors/errors_test.go
Bartlomiej Plotka 3d4af678c0 MultiError: Rename priv types, added support for errors.{As,Is}; tests.
Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com>
2020-12-23 21:16:19 +00:00

234 lines
7.1 KiB
Go

// Copyright 2016 The etcd Authors
//
// 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 errors_test
import (
stderrors "errors"
"testing"
pkgerrors "github.com/pkg/errors"
"github.com/prometheus/prometheus/tsdb/errors"
"github.com/stretchr/testify/require"
)
func TestNilMultiError(t *testing.T) {
require.NoError(t, errors.NewMulti().Err())
require.NoError(t, errors.NewMulti(nil, nil, nil).Err())
e := errors.NewMulti()
e.Add()
require.NoError(t, e.Err())
e = errors.NewMulti(nil, nil, nil)
e.Add()
require.NoError(t, e.Err())
e = errors.NewMulti()
e.Add(nil, nil, nil)
require.NoError(t, e.Err())
e = errors.NewMulti(nil, nil, nil)
e.Add(nil, nil, nil)
require.NoError(t, e.Err())
}
func TestMultiError(t *testing.T) {
err := stderrors.New("test1")
require.Error(t, errors.NewMulti(err).Err())
require.Error(t, errors.NewMulti(nil, err, nil).Err())
e := errors.NewMulti(err)
e.Add()
require.Error(t, e.Err())
e = errors.NewMulti(nil, nil, nil)
e.Add(err)
require.Error(t, e.Err())
e = errors.NewMulti(err)
e.Add(nil, nil, nil)
require.Error(t, e.Err())
e = errors.NewMulti(nil, nil, nil)
e.Add(nil, err, nil)
require.Error(t, e.Err())
require.Error(t, func() error {
return e.Err()
}())
require.NoError(t, func() error {
return errors.NewMulti(nil, nil, nil).Err()
}())
}
func TestMultiError_Error(t *testing.T) {
err := stderrors.New("test1")
require.Equal(t, "test1", errors.NewMulti(err).Err().Error())
require.Equal(t, "test1", errors.NewMulti(err, nil).Err().Error())
require.Equal(t, "4 errors: test1; test1; test2; test3", errors.NewMulti(err, err, stderrors.New("test2"), nil, stderrors.New("test3")).Err().Error())
}
type customErr struct{ error }
type customErr2 struct{ error }
type customErr3 struct{ error }
func TestMultiError_As(t *testing.T) {
err := customErr{error: stderrors.New("err1")}
require.True(t, stderrors.As(err, &err))
require.True(t, stderrors.As(err, &customErr{}))
require.False(t, stderrors.As(err, &customErr2{}))
require.False(t, stderrors.As(err, &customErr3{}))
// This is just to show limitation of std As.
require.False(t, stderrors.As(&err, &err))
require.False(t, stderrors.As(&err, &customErr{}))
require.False(t, stderrors.As(&err, &customErr2{}))
require.False(t, stderrors.As(&err, &customErr3{}))
e := errors.NewMulti(err).Err()
require.True(t, stderrors.As(e, &customErr{}))
same := errors.NewMulti(err).Err()
require.True(t, stderrors.As(e, &same))
require.False(t, stderrors.As(e, &customErr2{}))
require.False(t, stderrors.As(e, &customErr3{}))
e2 := errors.NewMulti(err, customErr3{error: stderrors.New("some")}).Err()
require.True(t, stderrors.As(e2, &customErr{}))
require.True(t, stderrors.As(e2, &customErr3{}))
require.False(t, stderrors.As(e2, &customErr2{}))
// Wrapped.
e3 := pkgerrors.Wrap(errors.NewMulti(err, customErr3{}).Err(), "wrap")
require.True(t, stderrors.As(e3, &customErr{}))
require.True(t, stderrors.As(e3, &customErr3{}))
require.False(t, stderrors.As(e3, &customErr2{}))
// This is just to show limitation of std As.
e4 := errors.NewMulti(err, &customErr3{}).Err()
require.False(t, stderrors.As(e4, &customErr2{}))
require.False(t, stderrors.As(e4, &customErr3{}))
}
func TestMultiError_Is(t *testing.T) {
err := customErr{error: stderrors.New("err1")}
require.True(t, stderrors.Is(err, err))
require.True(t, stderrors.Is(err, customErr{error: err.error}))
require.False(t, stderrors.Is(err, &err))
require.False(t, stderrors.Is(err, customErr{}))
require.False(t, stderrors.Is(err, customErr{error: stderrors.New("err1")}))
require.False(t, stderrors.Is(err, customErr2{}))
require.False(t, stderrors.Is(err, customErr3{}))
require.True(t, stderrors.Is(&err, &err))
require.False(t, stderrors.Is(&err, &customErr{error: err.error}))
require.False(t, stderrors.Is(&err, &customErr2{}))
require.False(t, stderrors.Is(&err, &customErr3{}))
e := errors.NewMulti(err).Err()
require.True(t, stderrors.Is(e, err))
require.True(t, stderrors.Is(err, customErr{error: err.error}))
require.True(t, stderrors.Is(e, e))
require.True(t, stderrors.Is(e, errors.NewMulti(err).Err()))
require.False(t, stderrors.Is(e, &err))
require.False(t, stderrors.Is(err, customErr{}))
require.False(t, stderrors.Is(e, customErr2{}))
require.False(t, stderrors.Is(e, customErr3{}))
e2 := errors.NewMulti(err, customErr3{}).Err()
require.True(t, stderrors.Is(e2, err))
require.True(t, stderrors.Is(e2, customErr3{}))
require.True(t, stderrors.Is(e2, errors.NewMulti(err, customErr3{}).Err()))
require.False(t, stderrors.Is(e2, errors.NewMulti(customErr3{}, err).Err()))
require.False(t, stderrors.Is(e2, customErr{}))
require.False(t, stderrors.Is(e2, customErr2{}))
// Wrapped.
e3 := pkgerrors.Wrap(errors.NewMulti(err, customErr3{}).Err(), "wrap")
require.True(t, stderrors.Is(e3, err))
require.True(t, stderrors.Is(e3, customErr3{}))
require.False(t, stderrors.Is(e3, customErr{}))
require.False(t, stderrors.Is(e3, customErr2{}))
exact := &customErr3{}
e4 := errors.NewMulti(err, exact).Err()
require.True(t, stderrors.Is(e4, err))
require.True(t, stderrors.Is(e4, exact))
require.True(t, stderrors.Is(e4, errors.NewMulti(err, exact).Err()))
require.False(t, stderrors.Is(e4, customErr{}))
require.False(t, stderrors.Is(e4, customErr2{}))
require.False(t, stderrors.Is(e4, &customErr3{}))
}
func TestMultiError_Count(t *testing.T) {
err := customErr{error: stderrors.New("err1")}
merr := errors.NewMulti()
merr.Add(customErr3{})
m, ok := errors.AsMulti(merr.Err())
require.True(t, ok)
require.Equal(t, 0, m.Count(err))
require.Equal(t, 1, m.Count(customErr3{}))
merr.Add(customErr3{})
merr.Add(customErr3{})
m, ok = errors.AsMulti(merr.Err())
require.True(t, ok)
require.Equal(t, 0, m.Count(err))
require.Equal(t, 3, m.Count(customErr3{}))
// Nest multi errors with wraps.
merr2 := errors.NewMulti()
merr2.Add(customErr3{})
merr2.Add(customErr3{})
merr2.Add(customErr3{})
merr3 := errors.NewMulti()
merr3.Add(customErr3{})
merr3.Add(customErr3{})
// Wrap it so Add cannot add inner errors in.
merr2.Add(pkgerrors.Wrap(merr3.Err(), "wrap"))
merr.Add(pkgerrors.Wrap(merr2.Err(), "wrap"))
m, ok = errors.AsMulti(merr.Err())
require.True(t, ok)
require.Equal(t, 0, m.Count(err))
require.Equal(t, 8, m.Count(customErr3{}))
}
func TestAsMulti(t *testing.T) {
err := customErr{error: stderrors.New("err1")}
merr := errors.NewMulti(err, customErr3{}).Err()
wrapped := pkgerrors.Wrap(merr, "wrap")
_, ok := errors.AsMulti(err)
require.False(t, ok)
m, ok := errors.AsMulti(merr)
require.True(t, ok)
require.True(t, stderrors.Is(m, merr))
m, ok = errors.AsMulti(wrapped)
require.True(t, ok)
require.True(t, stderrors.Is(m, merr))
}