/
githubmirror
/
etcd
Обзор
Документация
Войти
/
githubmirror
/
etcd
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
tests/robustness/validate/operations.go
110 строк
4 KB
Chun-Hung Tseng
Migrate to the new porcupine API for nondeterministic model
14 июл 2026, 10:43
14 июл 2026, 10:43
0c885da
Код
Авторство
О чём код?
// Copyright 2023 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 validate import ( "errors" "fmt" "time" "github.com/anishathalye/porcupine" "github.com/google/go-cmp/cmp" "go.uber.org/zap" "go.etcd.io/etcd/tests/v3/robustness/model" ) var ( errRespNotMatched = errors.New("response didn't match expected") errFutureRevRespRequested = errors.New("request about a future rev with response") ) func validateLinearizableOperationsAndVisualize(lg *zap.Logger, keys []string, operations []porcupine.Operation, timeout time.Duration) LinearizationResult { lg.Info("Validating linearizable operations", zap.Duration("timeout", timeout)) start := time.Now() m := model.NonDeterministicModel(keys) check, info := porcupine.CheckOperationsVerbose(m, operations, timeout) duration := time.Since(start) result := LinearizationResult{ Info: info, Model: m, } switch check { case porcupine.Ok: result.Status = Success lg.Info("Linearization success", zap.Duration("duration", duration)) case porcupine.Unknown: result.Status = Timeout result.Message = "timed out" lg.Error("Linearization timed out", zap.Duration("duration", duration)) case porcupine.Illegal: result.Status = Failure result.Message = "illegal" lg.Error("Linearization illegal", zap.Duration("duration", duration)) default: result.Status = Failure result.Message = fmt.Sprintf("unknown results from porcupine: %s", check) } return result } func validateSerializableOperations(lg *zap.Logger, operations []porcupine.Operation, replay *model.EtcdReplay) Result { lg.Info("Validating serializable operations") start := time.Now() err := validateSerializableOperationsError(lg, operations, replay) if err != nil { lg.Error("Serializable validation failed", zap.Duration("duration", time.Since(start)), zap.Error(err)) } else { lg.Info("Serializable validation success", zap.Duration("duration", time.Since(start))) } return ResultFromError(err) } func validateSerializableOperationsError(lg *zap.Logger, operations []porcupine.Operation, replay *model.EtcdReplay) (lastErr error) { for _, read := range operations { request := read.Input.(model.EtcdRequest) response := read.Output.(model.MaybeEtcdResponse) err := validateSerializableRead(lg, replay, request, response) if err != nil { lastErr = err } } return lastErr } func validateSerializableRead(lg *zap.Logger, replay *model.EtcdReplay, request model.EtcdRequest, response model.MaybeEtcdResponse) error { if response.Persisted || response.Error != "" { return nil } state, err := replay.StateForRevision(request.Range.Revision) if err != nil { if response.Error == model.ErrEtcdFutureRev.Error() { return nil } lg.Error("Failed validating serializable operation", zap.Any("request", request), zap.Any("response", response)) return errFutureRevRespRequested } _, expectResp := state.Step(request) if diff := cmp.Diff(response.EtcdResponse.Range, expectResp.Range); diff != "" { lg.Error("Failed validating serializable operation", zap.Any("request", request), zap.String("diff", diff)) return errRespNotMatched } return nil }