108 строки
5.3 KiB
Markdown
108 строки
5.3 KiB
Markdown
# `Coyote`
|
|
|
|
[![NuGet](https://img.shields.io/nuget/v/Microsoft.Coyote.svg)](https://www.nuget.org/packages/Microsoft.Coyote/)
|
|
[![Follow on Twitter](https://img.shields.io/twitter/follow/coyote_dev?style=social&logo=twitter)](https://twitter.com/intent/follow?screen_name=coyote_dev)
|
|
|
|
![Build and Test CI](https://github.com/microsoft/coyote/actions/workflows/test-coyote.yml/badge.svg?branch=main)
|
|
![CodeQL](https://github.com/microsoft/coyote/actions/workflows/codeql-analysis.yml/badge.svg?branch=main)
|
|
|
|
Coyote is a library and tool for testing concurrent C# code and deterministically reproducing bugs.
|
|
|
|
Using Coyote, you can easily test the *concurrency* and other *nondeterminism* in your C# code, by
|
|
writing what we call a *concurrency unit test*. These look like your regular unit tests, but can
|
|
reliably test concurrent workloads (such as actors, tasks, or concurrent requests to ASP.NET
|
|
controllers). In regular unit tests, you would typically avoid concurrency due to flakiness, but
|
|
with Coyote you are encouraged to embrace concurrency in your tests to find bugs.
|
|
|
|
Coyote is used by many teams in [Azure](https://azure.microsoft.com/) to test their distributed
|
|
systems and services, and has found hundreds of concurrency-related bugs before deploying code
|
|
in production and affecting users. In the words of an Azure service architect:
|
|
> Coyote found several issues early in the dev process, this sort of issues that would usually bleed
|
|
> through into production and become very expensive to fix later.
|
|
|
|
Coyote is made with :heart: by Microsoft Research.
|
|
|
|
**New:** Check out our experimental [systematic testing library for
|
|
C++](https://github.com/microsoft/cpp-systematic-testing) that is based on the same research and
|
|
technology that powers Coyote.
|
|
|
|
## How it works?
|
|
|
|
Consider the following simple test:
|
|
```csharp
|
|
[Fact]
|
|
public async Task TestTask()
|
|
{
|
|
int value = 0;
|
|
Task task = Task.Run(() =>
|
|
{
|
|
value = 1;
|
|
});
|
|
|
|
Assert.Equal(0, value);
|
|
await task;
|
|
}
|
|
```
|
|
|
|
This test will pass most of the time because the assertion will typically execute before the task
|
|
starts, but there is one schedule where the task starts fast enough to set `value` to `1` causing
|
|
the assertion to fail. Of course, this is a very naive example and the bug is obvious, but you could
|
|
imagine much more complicated race conditions that are hidden in complex execution paths.
|
|
|
|
The way Coyote works, is that you first convert the above test to a concurrency unit test using the
|
|
Coyote `TestingEngine` API:
|
|
```csharp
|
|
using Microsoft.Coyote.SystematicTesting;
|
|
|
|
[Fact]
|
|
public async Task CoyoteTestTask()
|
|
{
|
|
var configuration = Configuration.Create().WithTestingIterations(10);
|
|
var engine = TestingEngine.Create(configuration, TestTask);
|
|
engine.Run();
|
|
}
|
|
```
|
|
|
|
Next, you run the `coyote rewrite` command from the CLI (typically as a post-build task) to
|
|
automatically rewrite the IL of your test and production binaries. This allows Coyote to inject
|
|
hooks that take control of the concurrent execution during testing.
|
|
|
|
You can then run the concurrent unit test from your favorite unit testing framework (such as
|
|
[xUnit](https://xunit.net/)). Coyote will take over and repeatedly execute the test from
|
|
beginning to the end for N iterations (in the above example N was configured to `10`). Under the
|
|
hood, Coyote uses intelligent search strategies to explore all kinds of execution paths that might
|
|
hide a bug in each iteration.
|
|
|
|
The awesome thing is that once a bug is found, Coyote gives you a trace through the `engine.TestReport`
|
|
API that you can use to reliably *reproduce* the bug as many times as you want, making debugging and
|
|
fixing the issue significantly easier.
|
|
|
|
## Get started
|
|
|
|
Getting started with Coyote is easy! Check out
|
|
[https://microsoft.github.io/coyote](https://microsoft.github.io/coyote/) for tutorials,
|
|
documentation, how-tos, samples and more information about the project. Enjoy!
|
|
|
|
If you are a Microsoft employee, please consider joining the internal-only [Friends of Coyote Teams
|
|
channel](https://teams.microsoft.com/l/channel/19%3a1fe966b4fdc544bca648d89bf25c3c56%40thread.tacv2/General?groupId=7a6d8afc-c23d-4e5d-b9cb-9124118c0220&tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47),
|
|
to be part of our community and learn from each other. Otherwise, please feel free to start a
|
|
[discussion](https://github.com/microsoft/coyote/discussions) with us or open an
|
|
[issue](https://github.com/microsoft/coyote/issues) on GitHub, thank you!
|
|
|
|
## Contributing
|
|
|
|
This project welcomes contributions and suggestions. Most contributions require you to agree to a
|
|
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
|
|
the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
|
|
|
|
When you submit a pull request, a CLA bot will automatically determine whether you need to provide a
|
|
CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions
|
|
provided by the bot. You will only need to do this once across all repositories using our CLA.
|
|
|
|
## Code of Conduct
|
|
|
|
This project has adopted the [Microsoft Open Source Code of
|
|
Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of
|
|
Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact
|
|
[opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|