### Install Testo Source: https://github.com/ozontech/testo/blob/main/README.md Install the Testo package using go get. ```bash go get github.com/ozontech/testo ``` -------------------------------- ### Install and Build VSCode Testo Extension Source: https://github.com/ozontech/testo/blob/main/vscode-extension/README.md Steps to clone the repository, install dependencies, and build the extension from source. ```bash git clone https://github.com/ozontech/testo.git cd testo/vscode-extension npm i vsce package ``` -------------------------------- ### Running Tests with Go Source: https://github.com/ozontech/testo/blob/main/examples/README.md Command to run tests for a specific example using Go. Includes verbose output and example tag, with no caching. ```bash go test . -v -tags example -count=1 ``` -------------------------------- ### Example: Parallel Tests in Testo Source: https://github.com/ozontech/testo/blob/main/README.md Illustrates how to speed up tests by running them concurrently using Testo. This example is located in main_test.go within the examples/05_parallel directory. ```Go package main import ( "fmt" "time" "github.com/ozontech/testo" ) func main() { testo.NewSuite(t). Run("Test suite", func(s *testo.Suite) { s.ParallelTest("Test case 1", func(t *testo.T) { t.Sleep(time.Second) t.Assert().True(true) }) s.ParallelTest("Test case 2", func(t *testo.T) { t.Sleep(time.Second) t.Assert().True(true) }) }) } ``` -------------------------------- ### Example: Plugins in Testo Source: https://github.com/ozontech/testo/blob/main/README.md Demonstrates how to adapt tests to specific scenarios using Testo's plugin system. This example is located in the main_test.go file within the examples/04_plugins directory. ```Go package main import ( "fmt" "github.com/ozontech/testo" "github.com/ozontech/testo/plugins/assert" ) func main() { testo.NewSuite(t). Plugin(assert.New()). Run("Test suite", func(s *testo.Suite) { s.Test("Test case", func(t *testo.T) { t.Assert().Equal(1, 1) }) }) } ``` -------------------------------- ### Example: Parametrized Tests in Testo Source: https://github.com/ozontech/testo/blob/main/README.md Shows how to define a test once and run it with different parameters using Testo. This example is found in main_test.go within the examples/03_parametrized directory. ```Go package main import ( "fmt" "github.com/ozontech/testo" ) func main() { testo.NewSuite(t). Run("Test suite", func(s *testo.Suite) { s.ParametrizedTest("Test case", []testo.Param{ {Values: []any{1, 1, true}}, {Values: []any{2, 2, true}}, {Values: []any{3, 4, false}}, }, func(t *testo.T) { var a, b int var expected bool t.Param.Unmarshal(&a, &b, &expected) t.Assert().Equal(a+b > 0, expected) }) }) } ``` -------------------------------- ### Example: Lifecycle Hooks in Testo Source: https://github.com/ozontech/testo/blob/main/README.md Demonstrates the use of lifecycle hooks for actions before and after suites, tests, and sub-tests in Testo. This example is found in main_test.go within the examples/02_hooks directory. ```Go package main import ( "fmt" "github.com/ozontech/testo" ) func main() { testo.NewSuite(t). BeforeSuite(func() { fmt.Println("Before suite") }). AfterSuite(func() { fmt.Println("After suite") }). BeforeTest(func() { fmt.Println("Before test") }). AfterTest(func() { fmt.Println("After test") }). Run("Test suite", func(s *testo.Suite) { s.Test("Test case", func(t *testo.T) { t.Assert().True(true) }) }) } ``` -------------------------------- ### Example: Test Annotations in Testo Source: https://github.com/ozontech/testo/blob/main/README.md Shows how to attach static options to any test using Testo's annotation feature. This example is located in main_test.go within the examples/07_annotations directory. ```Go package main import ( "fmt" "github.com/ozontech/testo" ) func main() { testo.NewSuite(t). Run("Test suite", func(s *testo.Suite) { s.AnnotatedTest("Test case", testo.Annotation{ Skip: true, Message: "Skipping this test for now", }, func(t *testo.T) { t.Assert().True(true) }) }) } ``` -------------------------------- ### Example: Informative Errors and Traces in Testo Source: https://github.com/ozontech/testo/blob/main/README.md Demonstrates how Testo provides informative errors and traces to help diagnose issues. This example is found in main_test.go within the examples/06_errors directory. ```Go package main import ( "fmt" "github.com/ozontech/testo" "github.com/ozontech/testo/plugins/assert" ) func main() { testo.NewSuite(t). Plugin(assert.New()). Run("Test suite", func(s *testo.Suite) { s.Test("Test case", func(t *testo.T) { t.Assert().Equal(1, 2, "Expected 1 to equal 2") }) }) } ``` -------------------------------- ### Install VSCode Testo Extension VSIX Source: https://github.com/ozontech/testo/blob/main/vscode-extension/README.md Command to install the built VSCode extension VSIX file. ```bash code --install-extension testo-1.0.0.vsix ``` -------------------------------- ### Plugin Dependency Injection Example Source: https://github.com/ozontech/testo/blob/main/docs/technical-overview.md Demonstrates how to structure plugins in Testo using embedded structs to achieve dependency injection, ensuring shared instances. ```go type PluginX struct { *testo.T *PluginY } type PluginY struct { *testo.T } type T struct { *testo.T *PluginX *PluginY } ``` -------------------------------- ### Go Module for Testo Source: https://github.com/ozontech/testo/blob/main/README.md Shows the go.mod file indicating Testo has zero dependencies. This is a minimal example. ```Go module github.com/ozontech/testo go 1.18 ``` -------------------------------- ### Define a Test Suite Source: https://github.com/ozontech/testo/blob/main/docs/how-to.md Example of a basic Testo suite structure with two test methods. ```go type MySuite struct { testo.Suite[T] } func (MySuite) TestFoo(t T) { // ... } func (MySuite) TestBar(t T) { // ... } ``` -------------------------------- ### Define Outer and Inner Suites for Sub-Suite Execution Source: https://github.com/ozontech/testo/blob/main/docs/how-to.md Example demonstrating how to define an outer suite that runs an inner suite using testo.RunSubSuite. ```go type OuterSuite struct{ testo.Suite[T] } func (OuterSuite) Test(t T) { testo.RunSubSuite(t, new(InnerSuite)) } type InnerSuite struct{ testo.Suite[T] } func (InnerSuite) Test(t T) { t.Log("Hello from sub-suite!") } ``` -------------------------------- ### Example Test Output from `go test -v` Source: https://github.com/ozontech/testo/blob/main/docs/tutorial.md Illustrates the expected output when running tests with `go test -v`, showing the PASS status for the main test, the suite, Testo's internal test, and the specific test method. ```txt === RUN Test === RUN Test/Suite === RUN Test/Suite/testo! === RUN Test/Suite/testo!/TestAdd --- PASS: Test (0.00s) --- PASS: Test/Suite (0.00s) --- PASS: Test/Suite/testo! (0.00s) --- PASS: Test/Suite/testo!/TestAdd (0.00s) PASS ``` -------------------------------- ### Implement Test Logic in a Suite Source: https://github.com/ozontech/testo/blob/main/docs/how-to.md Implement the actual test logic for a specific suite. This example shows a simple test case that logs a message. ```go package suitefoo import "github.com/ozontech/testo" // An actual test logic for this suite goes here. type Suite struct{ testo.Suite[T] } func (*Suite) TestItWorks(t T) { t.Log("works!") } ``` -------------------------------- ### Writing a Timer Plugin Source: https://github.com/ozontech/testo/blob/main/docs/tutorial.md Implements a Testo plugin to measure the execution time of each test. It uses `BeforeEach` and `AfterEach` hooks to record the start time and calculate the elapsed duration. ```go type Timer struct { *testo.T start time.Time } func (t *Timer) Plugin(testoplugin.Plugin, ...testoplugin.Option) testoplugin.Spec { return testoplugin.Spec{ Hooks: testoplugin.Hooks{ BeforeEach: testoplugin.Hook{ Priority: testoplugin.TryLast, Func: func() { // the .Plugin method is called for each (sub-)test, // so we can modify fields without risk of synchronization errors. t.start = time.Now() }, }, AfterEach: testoplugin.Hook{ Priority: testoplugin.TryFirst, Func: func() { elapsed := time.Since(t.start) fmt.Printf("Test %q took %s\n", t.Name(), elapsed) }, }, }, } } ``` -------------------------------- ### Suite Hooks Example Source: https://github.com/ozontech/testo/blob/main/docs/tutorial.md Define BeforeEach and AfterEach hooks for a test suite. These methods are called before and after each test, respectively, and receive the test context `T`. ```go func (*Suite) BeforeEach(t T) { t.Logf("Starting: %s", t.Name()) } func (*Suite) AfterEach(t T) { t.Logf("Finished: %s", t.Name()) } ``` -------------------------------- ### Parametrized Test Execution Example Source: https://github.com/ozontech/testo/blob/main/docs/how-to.md Illustrates the combinations of parameters Testo will use to invoke a parametrized test based on the defined CasesXxx methods. ```python TestFoo(name=John, age=18) TestFoo(name=John, age=60) TestFoo(name=John, age=6) TestFoo(name=Joe, age=18) TestFoo(name=Joe, age=60) TestFoo(name=Joe, age=6) ``` -------------------------------- ### Basic Testo Test Source: https://github.com/ozontech/testo/blob/main/README.md A simple example of a Testo test case. This test logs a message using Testo's T object. ```go package main import ( "testing" "github.com/ozontech/testo" ) func Test(t *testing.T) { testo.RunTest(t, func(t *testo.T) { t.Log("Hello, Testo!") }) } ``` -------------------------------- ### Using AddNewMethods Plugin in a Test Source: https://github.com/ozontech/testo/blob/main/docs/tutorial.md Demonstrates how to call a method from an embedded plugin (`AddNewMethods`) directly on the test context (`T`). This requires the plugin to be installed in the `T` struct. ```go func (*Suite) TestBoom(t T) { t.Explode() } ``` -------------------------------- ### Define a Test Suite with Test Methods Source: https://github.com/ozontech/testo/blob/main/docs/tutorial.md Defines a test suite by embedding `testo.Suite[T]` and includes a test method `TestAdd`. Test methods must start with 'Test' and use the `T` type. ```go type Suite struct{ testo.Suite[T] } // Tests in Suites are regular methods, following the same // naming rules as regular tests in Go. // That means they must have the "Test" prefix. // They also must use the same type T as specified in `testo.Suite[T]`. func (*Suite) TestAdd(t T) { if Add(2, 2) != 4 { t.Fatal("2 + 2 must equal 4") } } ``` -------------------------------- ### Create and Initialize a New Go Project Source: https://github.com/ozontech/testo/blob/main/docs/tutorial.md Sets up a new Go project directory and initializes a Go module. This is the first step before writing any code or tests. ```bash mkdir testo-tutorial cd testo-tutorial go mod init testo-tutorial ``` -------------------------------- ### Run Testo Tests Source: https://github.com/ozontech/testo/blob/main/README.md Run your Testo tests using the standard 'go test' command. ```bash go test . ``` -------------------------------- ### Running Parametrized Sub-tests with testo.Run Source: https://github.com/ozontech/testo/blob/main/docs/tutorial.md Demonstrates how to run parametrized sub-tests using `testo.Run` for commutative and associative checks. This pattern is useful for testing properties of functions with different input parameters. ```go func (*Suite) CasesC() []int { return []int{-4, -99, 9} } func (*Suite) TestAddButParametrized(t T, p struct{ A, B, C int }) { testo.Run(t, "commutative", func(t T) { if Add(p.A, p.B) != Add(p.B, p.A) { t.Errorf("%[1]d + %[2]d != %[2]d + %[1]d", p.A, p.B) } }) testo.Run(t, "associative", func(t T) { if Add(Add(p.A, p.B), p.C) != Add(p.A, Add(p.B, p.C)) { t.Errorf("(%[1]d + %[2]d) + %[3]d != %[1]d + (%[2]d + %[3]d)", p.A, p.B, p.C) } }) } ``` -------------------------------- ### Run a Test Suite Source: https://github.com/ozontech/testo/blob/main/docs/how-to.md Run a defined test suite in your integration tests. Use build tags to control when specific suites are executed. ```go //go:build integration package tests import ( "testing" "example/tests/suite/suitefoo" "github.com/ozontech/testo" ) // In this file we actually run our suites. // The reason for starting tests here is that // single file makes it easier to see what suites will we run or skip. // // Moreover, if you add some build tag, like we do here ("integration" on the top), // specifying it only once makes it less typo-prone. func TestSuiteFoo(t *testing.T) { testo.RunSuite(t, new(suitefoo.Suite)) } ``` -------------------------------- ### Pass Plugin Options to Run Source: https://github.com/ozontech/testo/blob/main/docs/how-to.md Apply plugin options to specific sub-tests by passing them as arguments to the `testo.Run` function. ```go func (s *Suite) TestFoo(t *testo.T) { testo.Run(t, "my sub-test", func(t *testo.T) { // ... }, myplugin.SomeOption()) } ``` -------------------------------- ### Use Global Plugin Options with testo.Options Source: https://github.com/ozontech/testo/blob/main/docs/how-to.md Define global plugin options using `testo.Options` which are then automatically applied to all subsequent `testo.RunSuite` calls within the same test function. ```go var _ = testo.Options( myplugin.SomeOption(), otherplugin.OtherOption(42), ) func Test(t *testing.T) { // options are automatically passed to these RunSuite calls. testo.RunSuite(t, new(Suite)) testo.RunSuite(t, new(OtherSuite)) } ``` -------------------------------- ### Pass Plugin Options to RunSuite Source: https://github.com/ozontech/testo/blob/main/docs/how-to.md Configure plugins by passing their options directly to the `testo.RunSuite` function when initializing a test suite. ```go func Test(t *testing.T) { testo.RunSuite( t, new(Suite), myplugin.SomeOption(), otherplugin.OtherOption(42), ) testo.RunSuite( t, new(OtherSuite), anotherplugin.Option("..."), ) } ``` -------------------------------- ### Run Testo Suites with `go test` Source: https://github.com/ozontech/testo/blob/main/docs/tutorial.md Connects Testo to the standard `go test` command by calling `testo.RunSuite` within a regular Go test function. This enables Testo's features during test execution. ```go func Test(t *testing.T) { testo.RunSuite(t, new(Suite)) } ``` -------------------------------- ### Set Up Testo Alias for Testing Source: https://github.com/ozontech/testo/blob/main/docs/tutorial.md Creates a type alias `T` for `*testo.T` to simplify test method signatures. This is a common practice when using Testo. ```go package main import ( testing "testing" "github.com/ozontech/testo" ) type T = *testo.T ``` -------------------------------- ### Execute Go Tests with Verbose Output Source: https://github.com/ozontech/testo/blob/main/docs/tutorial.md Runs the Go tests in the current directory with verbose output enabled. This command shows the execution of each test and suite, including Testo's internal tests. ```bash go test . -v ``` -------------------------------- ### Enable Strict Mode with CLI Flag Source: https://github.com/ozontech/testo/blob/main/docs/how-to.md Run tests in strict mode by passing the -testo.strict flag to the 'go test' command. This turns zero value warnings into fatal errors. ```bash go test ./... -testo.strict ``` -------------------------------- ### Create a Test Suite Type Source: https://github.com/ozontech/testo/blob/main/docs/how-to.md Define a custom test suite type that embeds the global common plugin. This allows access to common functionalities within your tests. ```go package suitefoo import "example/tests/testcommon" // Global (common) T used by all suites. type T struct { *testo.T *testcommon.PluginCommon } ``` -------------------------------- ### Testo Execution Lifecycle Source: https://github.com/ozontech/testo/blob/main/docs/technical-overview.md This outlines the sequence of events when testo.RunSuite is called, including plugin initialization, hook execution, and test case running. ```text A root test named the same as a suite is run { Suite tests are collected and verified. Plugins are collected and initialized with ".Plugin(parent: nil, options)" method call, if implemented. Innermost plugins are initialized first. "BeforeAll" plugin hooks are called. "BeforeAll" suite hook is called. "CasesXXX" functions are called and parametrized tests are collected. Test plan from plugins is applied to the final test collection. A test named "testo!" is run { For each test in collection { Plugins are collected and initialized with ".Plugin(parent: parent, options)" method call, if implemented. Innermost plugins are initialized first. "BeforeEach" plugin hooks are called. "BeforeEach" suite hook is called. Actual test is run { For each sub-test in test (ran through "testo.Run") { Plugins are collected and initialized with ".Plugin(parent: parent, options)" method call, if implemented. Innermost plugins are initialized first. "BeforeEachSub" plugin hooks are called. Actual sub-test is run. For any sub-sub-...-test the same logic applies. "AfterEachSub" plugin hooks are called. } } "AfterEach" suite hook is called. "AfterEach" plugin hooks are called. } } "AfterAll" suite hook is called. "AfterAll" plugin hooks are called. } ``` -------------------------------- ### Parallel Sub-tests and Hook Execution Source: https://github.com/ozontech/testo/blob/main/docs/how-to.md Demonstrates how parallel sub-tests behave with respect to `AfterEach` hooks. The hook runs before parallel sub-tests complete. ```go func (*Suite) Test(t T) { testo.Run(t, "my sub-test", func(t T) { testo.Run(t, "sub-sub-test 1", func(t T) { t.Parallel() time.Sleep(time.Second) }) testo.Run(t, "sub-sub-test 2", func(t T) { t.Parallel() time.Sleep(time.Second) }) // AfterEach would run here. // But these parallel sub-tests will run later, not now. }) } ``` -------------------------------- ### Define a Simple Add Function in Go Source: https://github.com/ozontech/testo/blob/main/docs/tutorial.md Defines a basic `Add` function that sums two integers. This function will be used as a target for testing in the tutorial. ```go package main // Add returns sum of the given integers. func Add(a, b int) int { return a + b } func main() {} ``` -------------------------------- ### Define Parameter Cases Source: https://github.com/ozontech/testo/blob/main/docs/how-to.md Create CasesXxx methods in your test suite to define the possible values for each parameter. These methods are invoked after the BeforeAll hook. ```go func (*Suite) CasesName() []string { return []string{"John", "Joe"} } ``` ```go func (*Suite) CasesAge() []int { return []int{18, 60, 6} } ``` -------------------------------- ### Define a Global Test Plugin Source: https://github.com/ozontech/testo/blob/main/docs/how-to.md Define a global plugin for common test functionality. This approach minimizes future refactoring when adding new plugins. ```go package testcommon import ( "github.com/ozontech/testo" "github.com/ozontech/testo/testoplugin" ) // Here we define a global plugin common for all tests. // // It is highly advised to make it even if you don't use any plugins yet, // as in the future it won't require any further changes in other files if you // decide to add plugins. type PluginCommon struct { *testo.T } // This method implements Plugin interface. func (*PluginCommon) Plugin(testoplugin.Plugin, ...testoplugin.Option) testoplugin.Spec { return testolpugin.Spec{} } ``` -------------------------------- ### Writing a ReverseTestsOrder Plugin Source: https://github.com/ozontech/testo/blob/main/docs/tutorial.md Implements a Testo plugin that reverses the order of tests to be executed. This is achieved by modifying the test plan using the `Modify` hook. ```go import ( "github.com/ozontech/testo" "github.com/ozontech/testo/plugin" ) // We can embed testo.T in plugins - it will point to the same T // as in the current test. type ReverseTestsOrder struct{ *testo.T } // Plugins must implement this function // so that testo understands it's a plugin and can handle it correctly. func (*ReverseTestsOrder) Plugin(testoplugin.Plugin, ...testoplugin.Option) testoplugin.Spec { return testoplugin.Spec{ Plan: testoplugin.Plan{ Modify: func(tests *[]testoplugin.PlannedTest) { slices.Reverse(*tests) }, }, } } ``` -------------------------------- ### Writing an AddNewMethods Plugin Source: https://github.com/ozontech/testo/blob/main/docs/tutorial.md A placeholder plugin that demonstrates how to add new methods to the test context (`T`). This plugin defines an `Explode` method that calls `t.Fatal`. ```go type AddNewMethods struct{ *testo.T } func (*AddNewMethods) Plugin(testoplugin.Plugin, ...testoplugin.Option) testoplugin.Spec { // We have nothing to use here, so we return an empty specification return testoplugin.Spec{} } // Later we will see how we can call this method from tests. func (a *AddNewMethods) Explode() { a.Fatal("BOOM") } ``` -------------------------------- ### Running a Single Test Without a Suite Source: https://github.com/ozontech/testo/blob/main/docs/tutorial.md Use this method to run a single test function directly without defining a formal test suite. Ensure the 'T' struct includes necessary embedded types like '*testo.T'. ```go type T struct{ *testo.T *ReverseTestsOrder *OverrideLog *AddNewMethods *Timer } func TestFoo(t *testing.T) { testo.RunSuite(t, func(t T) { t.Log("Hello from testo!") }) } ``` -------------------------------- ### Writing an OverrideLog Plugin Source: https://github.com/ozontech/testo/blob/main/docs/tutorial.md Creates a Testo plugin that overrides the `t.Log` method to add custom behavior, such as printing a message before the original log is called. This demonstrates the use of the `Overrides` hook. ```go type OverrideLog struct { *testo.T } func (*OverrideLog) Plugin(testoplugin.Plugin, ...testoplugin.Option) testoplugin.Spec { return testoplugin.Spec{ Overrides: testoplugin.Overrides{ Log: func(f testoplugin.FuncLog) testoplugin.FuncLog { return func(args ...any) { // will be called each time t.Log is called fmt.Println("Inside log override") f(args...) } }, }, } } ``` -------------------------------- ### Run Specific Test in Suite Source: https://github.com/ozontech/testo/blob/main/docs/how-to.md Command to run a specific test method within a Testo suite using the -testo.m flag. ```shell go test . -run ./MySuite -testo.m TestFoo ``` -------------------------------- ### Handle Zero Values Warning Source: https://github.com/ozontech/testo/blob/main/docs/how-to.md Testo logs a warning if a CasesXxx function returns zero values, indicating that the corresponding test will not run. This log message shows the format of such a warning. ```text main_test.go:15: testo: (*main.Suite).CasesName provides zero values, (*main.Suite).TestFoo won't run ``` -------------------------------- ### Parametrized Test Cases for 'A' Source: https://github.com/ozontech/testo/blob/main/docs/tutorial.md Define the possible integer values for the parameter 'A' used in parametrized tests. This method should return a slice of integers. ```go func (*Suite) CasesA() []int { return []int{1, 2, 3, 4, 5} } ``` -------------------------------- ### Parametrized Test Cases for 'B' Source: https://github.com/ozontech/testo/blob/main/docs/tutorial.md Define the possible integer values for the parameter 'B' used in parametrized tests. This method should return a slice of integers. ```go func (*Suite) CasesB() []int { return []int{11, 1000, 13} } ``` -------------------------------- ### Parametrized Test Function Source: https://github.com/ozontech/testo/blob/main/docs/tutorial.md Implement a test function that accepts parameters for parametrization. The test logic is defined within this function, which receives the test context `T` and a struct `p` containing the parameters. ```go func (*Suite) TestAddButParametrized(t T, p struct{ A, B int }) { if Add(p.A, p.B) != Add(p.B, p.A) { t.Errorf("%[1]d + %[2]d != %[2]d + %[1]d", p.A, p.B) } } ``` -------------------------------- ### Running Multiple Tests from a Single Function Source: https://github.com/ozontech/testo/blob/main/docs/tutorial.md Execute several tests within a single 'real' test function by using `t.Run` with `testo.Test`. This allows for organizing related tests under one umbrella. ```go func TestFoo(t *testing.T) { t.Run("FirstTest", testo.Test(func(t T) { t.Log("1!") })) t.Run("SecondTest", testo.Test(func(t T) { t.Log("2!") })) } ``` -------------------------------- ### Define a Parametrized Test Function Source: https://github.com/ozontech/testo/blob/main/docs/how-to.md Define a regular test function that accepts a second argument for parameters. The parameter struct field names must match the CasesXxx method names. ```go func (*Suite) TestFoo(t *testo.T, p struct{ Name string; Age int }) { t.Logf("Using name=%q and age=%d", p.Name, p.Age) } ``` -------------------------------- ### Register Cleanup Function in BeforeEach Source: https://github.com/ozontech/testo/blob/main/docs/how-to.md Use `t.Cleanup` within `BeforeEach` to manage resources or actions that need to be executed after a test, especially when dealing with parallel sub-tests. ```go func (*Suite) BeforeEach(t T) { t.Cleanup(t.afterEach) } ``` -------------------------------- ### Mark a Test as Parallel Source: https://github.com/ozontech/testo/blob/main/docs/how-to.md Use `t.Parallel()` within a test function to indicate that it can be run in parallel with other tests. ```go func (*Suite) TestFoo(t *testo.T) { t.Parallel() // your test here } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.