| /* |
| * Copyright 2019-present Open Networking Foundation |
| * |
| * 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 utils |
| |
| import ( |
| "math/rand" |
| "testing" |
| "time" |
| |
| "github.com/opencord/voltha-lib-go/v3/pkg/log" |
| "github.com/stretchr/testify/assert" |
| "google.golang.org/grpc/codes" |
| "google.golang.org/grpc/status" |
| ) |
| |
| var ( |
| timeoutError error |
| taskFailureError error |
| ) |
| |
| func init() { |
| _, err := log.AddPackage(log.JSON, log.WarnLevel, nil) |
| if err != nil { |
| log.Errorw("unable-to-register-package-to-the-log-map", log.Fields{"error": err}) |
| } |
| timeoutError = status.Errorf(codes.Aborted, "timeout") |
| taskFailureError = status.Error(codes.Internal, "test failure task") |
| } |
| |
| func runSuccessfulTask(response Response, durationRange int) { |
| time.Sleep(time.Duration(rand.Intn(durationRange)) * time.Millisecond) |
| response.Done() |
| } |
| |
| func runFailureTask(response Response, durationRange int) { |
| time.Sleep(time.Duration(rand.Intn(durationRange)) * time.Millisecond) |
| response.Error(taskFailureError) |
| } |
| |
| func runMultipleTasks(timeout, numTasks, taskDurationRange, numSuccessfulTask, numFailuretask int) []error { |
| if numTasks != numSuccessfulTask+numFailuretask { |
| return []error{status.Error(codes.FailedPrecondition, "invalid-num-tasks")} |
| } |
| numSuccessfulTaskCreated := 0 |
| responses := make([]Response, numTasks) |
| for i := 0; i < numTasks; i++ { |
| responses[i] = NewResponse() |
| if numSuccessfulTaskCreated < numSuccessfulTask { |
| go runSuccessfulTask(responses[i], taskDurationRange) |
| numSuccessfulTaskCreated++ |
| continue |
| } |
| go runFailureTask(responses[i], taskDurationRange) |
| } |
| return WaitForNilOrErrorResponses(int64(timeout), responses...) |
| } |
| |
| func getNumSuccessFailure(inputs []error) (numSuccess, numFailure, numTimeout int) { |
| numFailure = 0 |
| numSuccess = 0 |
| numTimeout = 0 |
| for _, input := range inputs { |
| if input != nil { |
| if input.Error() == timeoutError.Error() { |
| numTimeout++ |
| } |
| numFailure++ |
| } else { |
| numSuccess++ |
| } |
| } |
| return |
| } |
| |
| func TestNoTimeouts(t *testing.T) { |
| var ( |
| totalSuccess int |
| totalFailure int |
| results []error |
| nSuccess int |
| nFailure int |
| nTimeouts int |
| ) |
| numIterations := 5 |
| numTasks := 5 |
| for i := 0; i < numIterations; i++ { |
| totalSuccess = rand.Intn(numTasks) |
| totalFailure = numTasks - totalSuccess |
| results = runMultipleTasks(110, numTasks, 100, totalSuccess, totalFailure) |
| nSuccess, nFailure, nTimeouts = getNumSuccessFailure(results) |
| assert.Equal(t, totalFailure, nFailure) |
| assert.Equal(t, totalSuccess, nSuccess) |
| assert.Equal(t, 0, nTimeouts) |
| |
| } |
| } |
| |
| func TestSomeTasksTimeouts(t *testing.T) { |
| var ( |
| totalSuccess int |
| totalFailure int |
| results []error |
| nSuccess int |
| nFailure int |
| nTimeouts int |
| ) |
| numIterations := 5 |
| numTasks := 5 |
| for i := 0; i < numIterations; i++ { |
| totalSuccess = rand.Intn(numTasks) |
| totalFailure = numTasks - totalSuccess |
| results = runMultipleTasks(50, numTasks, 100, totalSuccess, totalFailure) |
| nSuccess, nFailure, nTimeouts = getNumSuccessFailure(results) |
| assert.True(t, nFailure >= totalFailure) |
| assert.True(t, nSuccess <= totalSuccess) |
| assert.True(t, nTimeouts > 0) |
| } |
| } |