From 086ab166bbbf17d3f0a16c8b27f1995a70908b35 Mon Sep 17 00:00:00 2001 From: Aleksandr Nogikh Date: Tue, 14 May 2024 16:52:34 +0200 Subject: pkg/fuzzer/queue: retry inputs from crashed VMs Mark some requests as Important. The Retry() layer will give them one more chance even if they were not executed due to a VM crash. For now, the only important requests are related to triage, candidates and pkg/vminfo tests. Add tests for retry.go. --- pkg/fuzzer/queue/retry_test.go | 72 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 pkg/fuzzer/queue/retry_test.go (limited to 'pkg/fuzzer/queue/retry_test.go') diff --git a/pkg/fuzzer/queue/retry_test.go b/pkg/fuzzer/queue/retry_test.go new file mode 100644 index 000000000..8529779a2 --- /dev/null +++ b/pkg/fuzzer/queue/retry_test.go @@ -0,0 +1,72 @@ +// Copyright 2024 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package queue + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestRetryerOnRestart(t *testing.T) { + q := Plain() + retryerObj := Retry(q) + + q.Submit(&Request{Important: true}) + q.Submit(&Request{Important: false}) + + // The requests must be retried forever. + req1 := retryerObj.Next() + req2 := retryerObj.Next() + for i := 0; i < 10; i++ { + req1.Done(&Result{Status: Restarted}) + req2.Done(&Result{Status: Restarted}) + assert.Equal(t, req1, retryerObj.Next()) + assert.Equal(t, req2, retryerObj.Next()) + } + + // Once successful, requests should no longer appear. + req1.Done(&Result{Status: Success}) + req2.Done(&Result{Status: Success}) + + assert.Equal(t, Success, req1.Wait(context.Background()).Status) + assert.Equal(t, Success, req2.Wait(context.Background()).Status) + + assert.Nil(t, retryerObj.Next()) + assert.Nil(t, retryerObj.Next()) +} + +func TestRetryerOnCrash(t *testing.T) { + q := Plain() + retryerObj := Retry(q) + + // Unimportant requests will not be retried. + req := &Request{Important: false} + q.Submit(req) + assert.Equal(t, req, retryerObj.Next()) + req.Done(&Result{Status: Crashed}) + assert.Nil(t, retryerObj.Next()) + assert.Equal(t, Crashed, req.Wait(context.Background()).Status) + + // Important requests will be retried once. + req = &Request{Important: true} + q.Submit(req) + assert.Equal(t, req, retryerObj.Next()) + req.Done(&Result{Status: Crashed}) + assert.Equal(t, req, retryerObj.Next()) + req.Done(&Result{Status: Success}) + assert.Nil(t, retryerObj.Next()) + assert.Equal(t, Success, req.Wait(context.Background()).Status) + + // .. but not more than once. + req = &Request{Important: true} + q.Submit(req) + assert.Equal(t, req, retryerObj.Next()) + req.Done(&Result{Status: Crashed}) + assert.Equal(t, req, retryerObj.Next()) + req.Done(&Result{Status: Crashed}) + assert.Nil(t, retryerObj.Next()) + assert.Equal(t, Crashed, req.Wait(context.Background()).Status) +} -- cgit mrf-deployment