Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#12: Add support for shimming async methods #29

Open
wants to merge 45 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
b8aff4e
#26 Change `thisType.IsValueType` to `constructor.IsValueType`
Miista May 2, 2024
211a5f5
#26 Add regression test for Miista/pose#26
Miista May 2, 2024
e388857
Update references to “Pose” with “Poser”
Miista May 2, 2024
afe5f08
Update Poser.nuspec
Miista May 2, 2024
6a440d0
Merge pull request #40 from Miista/26-enumisdefined-cannot-be-called-…
Miista May 2, 2024
eea75ec
#12 Add support for async methods
Miista May 2, 2024
bd96fa7
Fix last reference to “Pose”
Miista May 2, 2024
228cc2a
#36 Update badges in README
Miista May 2, 2024
570af2b
Merge pull request #41 from Miista/release/release-2.0.1
Miista May 2, 2024
da84ffd
#12 Add tests for shimming async methods
Miista May 2, 2024
f4904c7
Merge pull request #32 from Miista/28-update-readme-to-use-poser-nuge…
Miista May 2, 2024
d4ed536
Merge pull request #42 from Miista/36-update-badges-in-readme
Miista May 2, 2024
5a47ab3
#12 Successfully add support for async methods
Miista May 2, 2024
447b3ed
#12 Add net7.0 target to tests
Miista May 2, 2024
3ff8edb
#12 Clean up implementation
Miista May 2, 2024
b10d8b5
Merge remote-tracking branch 'origin/master' into 12-add-async-support
Miista May 2, 2024
9ed298f
#12 Bump version to 2.1.0-alpha0001
Miista May 2, 2024
95b9f35
#12: Add tests for async stubbing and getting the MoveNext method
Miista May 2, 2024
de427ae
#12 Add tests for more coverage
Miista May 2, 2024
599f7fc
Add more tests for coverage
Miista May 2, 2024
170a919
Remove redundant platform override #if
Miista May 2, 2024
1373e9d
Remove netcoreapp2.1 from test targets
Miista May 2, 2024
52e3c89
Remove netstandard2.1 from test target frameworks
Miista May 2, 2024
8db27e6
#12 Add examples to README
Miista May 2, 2024
3663b77
Swap usages of DEBUG with TRACE
Miista May 2, 2024
afcce01
#12 Begin adding tests for replacing async methods
Miista May 2, 2024
da34def
#12 Rearrange sections in README for clarity
Miista May 2, 2024
44e57ef
Merge remote-tracking branch 'origin/master' into 12-add-async-support
Miista May 2, 2024
cdf8430
#12 Emit leave instruction if rewriting an async method
Miista May 2, 2024
bef32fb
Update references to “Pose” with “Poser”
Miista Jan 16, 2025
a3df3d4
Fix last reference to “Pose”
Miista Jan 16, 2025
0e9881f
Merge pull request #32 from Miista/28-update-readme-to-use-poser-nuge…
Miista Jan 16, 2025
ddfb550
#26 Change `thisType.IsValueType` to `constructor.IsValueType`
Miista Jan 16, 2025
790b2ae
#26 Add regression test for Miista/pose#26
Miista Jan 16, 2025
d1a5a13
Update Poser.nuspec
Miista Jan 16, 2025
16abe83
Merge pull request #40 from Miista/26-enumisdefined-cannot-be-called-…
Miista Jan 16, 2025
297b8f1
#36 Update badges in README
Miista Jan 16, 2025
189685f
Merge pull request #41 from Miista/release/release-2.0.1
Miista Jan 16, 2025
9289b33
Merge pull request #42 from Miista/36-update-badges-in-readme
Miista Jan 16, 2025
e29b229
Merge remote-tracking branch 'refs/remotes/origin/master' into 12-add…
Miista Jan 16, 2025
0d2c6d7
#12: Add special case for rewriting AsyncMethodBuilderCore
Miista Jan 16, 2025
5874cc9
Something which works
Miista Jan 16, 2025
274d518
More stuff that nearly works
Miista Jan 16, 2025
697b39d
Successfully rewrite async method
Miista Jan 16, 2025
5b5908e
Add more code
Miista Jan 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
#12 Add examples to README
Miista committed May 2, 2024

Verified

This commit was signed with the committer’s verified signature.
commit 8db27e67472978f0215e214da909aa8c9e7945e3
58 changes: 58 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -115,8 +115,47 @@ Shim structShim = Shim.Replace(() => Is.A<MyStruct>().DoSomething()).With(

_Note: You cannot shim methods on specific instances of Value Types_

### Shim static async method
```csharp
using Pose;

Shim staticTaskShim = Shim.Replace(() => DoWorkAsync()).With(
delegate
{
Console.Write("refusing to do work");
return Task.CompletedTask;
});
```
### Shim async instance method of a Reference Type
```csharp
using Pose;

Shim instanceTaskShim = Shim.Replace(() => Is.A<MyClass>().DoSomethingAsync()).With(
delegate(MyClass @this)
{
Console.WriteLine("doing something else async");
return Task.CompletedTask;
});
```

### Shim method of specific instance of a Reference Type
_Not supported for now. When supported, however, it will look like the following._

```csharp
using Pose;

MyClass myClass = new MyClass();
Shim myClassTaskShim = Shim.Replace(() => myClass.DoSomethingAsync()).With(
delegate(MyClass @this)
{
Console.WriteLine("doing something else with myClass async");
return Task.CompletedTask;
});
```

### Isolating your code

#### Non-async
```csharp
// This block executes immediately
PoseContext.Isolate(() =>
@@ -139,6 +178,25 @@ PoseContext.Isolate(() =>
}, consoleShim, dateTimeShim, classPropShim, classShim, myClassShim, structShim);
```

#### Async
```csharp
// This block executes immediately
await PoseContext.Isolate(async () =>
{
// All code that executes within this block
// is isolated and shimmed methods are replaced
// Outputs "refusing to do work"
await DoWorkAsync();

// Outputs "doing something else async"
new MyClass().DoSomethingAsync();

// Outputs "doing something else with myClass async"
await myClass.DoSomethingAsync();

}, staticTaskShim, instanceTaskShim, myClassTaskShim);
```
## Caveats & Limitations

* **Breakpoints** - At this time any breakpoints set anywhere in the isolated code and its execution path will not be hit. However, breakpoints set within a shim replacement delegate are hit.
147 changes: 93 additions & 54 deletions src/Sandbox/Program.cs
Original file line number Diff line number Diff line change
@@ -7,71 +7,110 @@ namespace Pose.Sandbox
{
public class Program
{
internal class MyClass
{
public async Task DoSomethingAsync() => await Task.CompletedTask;
}

public static async Task<int> GetIntAsync()
{
Console.WriteLine("Here");
return await Task.FromResult(1);
}

public static async Task DoWorkAsync()
{
Console.WriteLine("Here");
await Task.Delay(1000);
}

public static void Main(string[] args)
public static async Task Main(string[] args)
{
#if NET48
Console.WriteLine("4.8");
var dateTimeShim = Shim.Replace(() => DateTime.Now).With(() => new DateTime(2004, 1, 1));
PoseContext.Isolate(
() =>
var staticAsyncShim = Shim.Replace(() => DoWorkAsync()).With(
delegate
{
Console.WriteLine(DateTime.Now);
}, dateTimeShim);
#elif NETCOREAPP2_0
Console.WriteLine("2.0");
//var dateTimeShim = Shim.Replace(() => DateTime.Now).With(() => new DateTime(2004, 1, 1));
var asyncShim = Shim.Replace(() => GetIntAsync()).With(() =>
{
Console.WriteLine("This actually works!!!");
return Task.FromResult(15);
});
PoseContext.Isolate(
Console.Write("Don't do work!");
return Task.CompletedTask;
});
var taskShim = Shim.Replace(() => Is.A<MyClass>().DoSomethingAsync())
.With(delegate(MyClass @this)
{
Console.WriteLine("Shimming async Task");
return Task.CompletedTask;
}
);
await PoseContext.Isolate(
async () =>
{
var result = await GetIntAsync();
Console.WriteLine($"Result: {result}");
//Console.WriteLine(DateTime.Now);
}, asyncShim);
#elif NET6_0
Console.WriteLine("6.0");
var dateTimeShim = Shim.Replace(() => DateTime.Now).With(() => new DateTime(2004, 1, 1));
PoseContext.Isolate(
() =>
{
Console.WriteLine(DateTime.Now);
}, dateTimeShim);
#elif NET7_0
Console.WriteLine("7.0");
await DoWorkAsync();
}, staticAsyncShim
);

var dateTimeShim = Shim.Replace(() => DateTime.Now).With(() => new DateTime(2004, 1, 1));
PoseContext.Isolate(
() =>
{
Console.WriteLine(DateTime.Now);
}, dateTimeShim);
#elif NETCOREAPP3_0
Console.WriteLine("3.0");
var dateTimeShim = Shim.Replace(() => DateTime.Now).With(() => new DateTime(2004, 1, 1));
PoseContext.Isolate(
() =>
{
Console.WriteLine(DateTime.Now);
}, dateTimeShim);
#else
Console.WriteLine("Other");
var dateTimeShim = Shim.Replace(() => DateTime.Now).With(() => new DateTime(2004, 1, 1));
PoseContext.Isolate(
() =>
{
Console.WriteLine(DateTime.Now);
}, dateTimeShim);
#endif
// #if NET48
// Console.WriteLine("4.8");
// var dateTimeShim = Shim.Replace(() => DateTime.Now).With(() => new DateTime(2004, 1, 1));
// PoseContext.Isolate(
// () =>
// {
// Console.WriteLine(DateTime.Now);
// }, dateTimeShim);
// #elif NETCOREAPP2_0
// Console.WriteLine("2.0");
// var asyncVoidShim = Shim.Replace(() => DoWorkAsync())
// .With(
// () =>
// {
// Console.WriteLine("Shimming async Task");
// return Task.CompletedTask;
// }
// );
// //var dateTimeShim = Shim.Replace(() => DateTime.Now).With(() => new DateTime(2004, 1, 1));
// var asyncShim = Shim.Replace(() => GetIntAsync()).With(() =>
// {
// Console.WriteLine("This actually works!!!");
// return Task.FromResult(15);
// });
// PoseContext.Isolate(
// async () =>
// {
// var result = await GetIntAsync();
// Console.WriteLine($"Result: {result}");
// //Console.WriteLine(DateTime.Now);
// }, asyncShim);
// #elif NET6_0
// Console.WriteLine("6.0");
// var dateTimeShim = Shim.Replace(() => DateTime.Now).With(() => new DateTime(2004, 1, 1));
// PoseContext.Isolate(
// () =>
// {
// Console.WriteLine(DateTime.Now);
// }, dateTimeShim);
// #elif NET7_0
// Console.WriteLine("7.0");
//
// var dateTimeShim = Shim.Replace(() => DateTime.Now).With(() => new DateTime(2004, 1, 1));
// PoseContext.Isolate(
// () =>
// {
// Console.WriteLine(DateTime.Now);
// }, dateTimeShim);
// #elif NETCOREAPP3_0
// Console.WriteLine("3.0");
// var dateTimeShim = Shim.Replace(() => DateTime.Now).With(() => new DateTime(2004, 1, 1));
// PoseContext.Isolate(
// () =>
// {
// Console.WriteLine(DateTime.Now);
// }, dateTimeShim);
// #else
// Console.WriteLine("Other");
// var dateTimeShim = Shim.Replace(() => DateTime.Now).With(() => new DateTime(2004, 1, 1));
// PoseContext.Isolate(
// () =>
// {
// Console.WriteLine(DateTime.Now);
// }, dateTimeShim);
// #endif

// var dateTimeShim = Shim.Replace(() => T.I).With(() => "L");
// var dateTimeShim1 = Shim.Replace(() => T.Get()).With(() => "Word");