-
Notifications
You must be signed in to change notification settings - Fork 19
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
Assignment9+10: Tyler + Austin #87
base: Assignment9+10-Multithreading
Are you sure you want to change the base?
Assignment9+10: Tyler + Austin #87
Conversation
…71-2024-Fall into Assignment9+10
…71-2024-Fall into Assignment9+10
…_UsingTpl_Success()
RunAsync_UsingTplWithCancellation_CatchAggregateExceptionWrapping() RunAsync_UsingTplWithCancellation_CatchAggregateExceptionWrappingTaskCanceledException()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really nice work boys! I only found one issue thats sort of a non issue ? I think that your returning the wrong type of exemption with the cancelation. It seems to work tho anyway.
Anyway any extra detail is left in comments -L
Implement PingProcess' public Task RunTaskAsync(string hostNameOrAddress) ✔
First implement public void RunTaskAsync_Success() test method to test PingProcess.RunTaskAsync() using "localhost". ✔
Do NOT use async/await in this implementation. ✔
Implement PingProcess' async public Task RunAsync(string hostNameOrAddress) ✔
First implement the public void RunAsync_UsingTaskReturn_Success() test method to test PingProcess.RunAsync() using "localhost" without using async/await. ✔
Also implement the async public Task RunAsync_UsingTpl_Success() test method to test PingProcess.RunAsync() using "localhost" but this time DO using async/await. ✔
Add support for an optional cancellation token to the PingProcess.RunAsync() signature. ✔
Inside the PingProcess.RunAsync() invoke the token's ThrowIfCancellationRequested() method so an exception is thrown. ✔
Test that, when cancelled from the test method, the exception thrown is an AggregateException ✔/ ?
with a TaskCanceledException inner exception ✔/ ?
using the test methods RunAsync_UsingTplWithCancellation_CatchAggregateExceptionWrapping ✔
and RunAsync_UsingTplWithCancellation_CatchAggregateExceptionWrappingTaskCanceledException ✔ respectively.
Complete/fix AND test async public Task RunAsync(IEnumerable hostNameOrAddresses, CancellationToken cancellationToken = default) which executes ping for an array of hostNameOrAddresses (which can all be "localhost") in parallel, adding synchronization if needed. ✔
NOTE:
The order of the items in the stdOutput is irrelevant and expected to be intermingled.
StdOutput must have all the ping output returned (no lines can be missing) even though intermingled. ✔
Implement AND test public Task RunLongRunningAsync(ProcessStartInfo startInfo, Action<string?>? progressOutput, Action<string?>? progressError, CancellationToken token) using Task.Factory.StartNew() and invoking RunProcessInternal with a TaskCreation value of TaskCreationOptions.LongRunning and a TaskScheduler value of TaskScheduler.Current. Returning a Task is also okay.
NOTE: This method does NOT use Task.Run. ✔
Extra Credit
Test and implement PingProcess.RunAsync(System.IProgress progess) so that you can capture the output as it occurs rather than capturing the output only when the process finishes. ❌
Fundamentals
Place all shared project properties into a Directory.Build.Props file.✔
Place all shared project items into a Directory.Build.targets file.✔
Ensure nullable reference types is enabled ✔
Ensure that you turn on code analysis for all projects(EnableNETAnalyzers) ✔
Set LangVersion and the TargetFramework to the latest released versions available (preview versions optional) ✔
and enabled .NET analyzers for both projects ✔
For this assignment, consider using Assert.AreEqual() (the generic version) ✔
All of the above should be unit tested ✔
Choose simplicity over complexity ✔
} | ||
|
||
[TestMethod] | ||
[ExpectedException(typeof(AggregateException))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Im not sure how you made this work. I had to flatten and rethrow as AggregateException here. When you cancel it should return a cancelationException
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought that it was an aggregate exception until you flatten it and pull out the inner exception, but we will look more into it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I am aware, any errors caused within a task results in an aggregate exception
catch (AggregateException ex) | ||
{ | ||
AggregateException flattened = ex.Flatten(); | ||
Assert.IsTrue(flattened.InnerExceptions.Any(e => e is TaskCanceledException), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this may be backwards CanceledExemption should be the default and Aggregate should be the one you flatten. It works like this but is kinda confusing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is my understanding that you flatten the Aggregate to get the TaskCanceledException but I could be wrong. I will look more into it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here they catch an aggregate exception and flatten it. A flattened aggregate is still an aggregate exception. They then call the inner exceptions and check if it is a TaskCanceled Exception, which should be fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Implement
PingProcess
'public Task<PingResult> RunTaskAsync(string hostNameOrAddress)
✔- First implement
public void RunTaskAsync_Success()
test method to testPingProcess.RunTaskAsync()
using"localhost"
. ✔ - Do NOT use async/await in this implementation. ✔
- First implement
- Implement
PingProcess
'async public Task<PingResult> RunAsync(string hostNameOrAddress)
✔- First implement the
public void RunAsync_UsingTaskReturn_Success()
test method to testPingProcess.RunAsync()
using"localhost"
without using async/await. ✔ - Also implement the
async public Task RunAsync_UsingTpl_Success()
test method to testPingProcess.RunAsync()
using"localhost"
but this time DO using async/await. ✔
- First implement the
- Add support for an optional cancellation token to the
PingProcess.RunAsync()
signature. ✔
- Inside the
PingProcess.RunAsync()
invoke the token'sThrowIfCancellationRequested()
method so an exception is thrown. ✔ - Test that, when cancelled from the test method, the exception thrown is an
AggregateException
✔- with a
TaskCanceledException
inner exception ✔ - using the test methods
RunAsync_UsingTplWithCancellation_CatchAggregateExceptionWrapping
✔ - and
RunAsync_UsingTplWithCancellation_CatchAggregateExceptionWrappingTaskCanceledException
✔ respectively.
- with a
- Complete/fix AND test
async public Task<PingResult> RunAsync(IEnumerable<string> hostNameOrAddresses, CancellationToken cancellationToken = default)
which executes ping for an array of hostNameOrAddresses (which can all be "localhost") in parallel, adding synchronization if needed. ✔
NOTE:- The order of the items in the stdOutput is irrelevant and expected to be intermingled.
- StdOutput must have all the ping output returned (no lines can be missing) even though intermingled. ❌
- Implement AND test
public Task<int> RunLongRunningAsync(ProcessStartInfo startInfo, Action<string?>? progressOutput, Action<string?>? progressError, CancellationToken token)
usingTask.Factory.StartNew()
and invokingRunProcessInternal
with aTaskCreation
value ofTaskCreationOptions.LongRunning
and aTaskScheduler
value ofTaskScheduler.Current
. Returning aTask<PingResult>
is also okay.✔
NOTE: This method does NOT useTask.Run
.✔
Extra Credit
- Test and implement
PingProcess.RunAsync(System.IProgress<T> progess)
so that you can capture the output as it occurs rather than capturing the output only when the process finishes. ❌✔
Fundamentals
- Place all shared project properties into a
Directory.Build.Props
file.✔ - Place all shared project items into a
Directory.Build.targets
file.✔ - Ensure nullable reference types is enabled ✔
- Ensure that you turn on code analysis for all projects(EnableNETAnalyzers) ✔
- Set
LangVersion
and theTargetFramework
to the latest released versions available (preview versions optional) ✔ - and enabled .NET analyzers for both projects ✔
- For this assignment, consider using
Assert.AreEqual<T>()
(the generic version) ✔ - All of the above should be unit tested ✔
- Choose simplicity over complexity ✔
Good work :)
} | ||
|
||
[TestMethod] | ||
[ExpectedException(typeof(AggregateException))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I am aware, any errors caused within a task results in an aggregate exception
catch (AggregateException ex) | ||
{ | ||
AggregateException flattened = ex.Flatten(); | ||
Assert.IsTrue(flattened.InnerExceptions.Any(e => e is TaskCanceledException), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here they catch an aggregate exception and flatten it. A flattened aggregate is still an aggregate exception. They then call the inner exceptions and check if it is a TaskCanceled Exception, which should be fine.
void updateStdOutput(string? line) => | ||
(stringBuilder ??= new StringBuilder()).AppendLine(line); | ||
|
||
Process process = RunProcessInternal(StartInfo, updateStdOutput, null, cancellationToken); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps add this within the Task.Run itself
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What are your thoughts on why it should be inside?
|
||
// Act | ||
Task task = Sut.RunAsync("localhost -c 4").ContinueWith(t => result = t.Result); | ||
task.Wait(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than continue with, perhaps using task.Wait() then just referring to task.Result may be easier to read
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will look into this. In your opinion would it just be easier or is it functionally better?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed that, I do feel like it's slightly more readable
|
||
// Assert | ||
Assert.IsFalse(string.IsNullOrWhiteSpace(result.StdOutput)); | ||
Assert.AreEqual(0, result.ExitCode); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- StdOutput must have all the ping output returned (no lines can be missing) even though intermingled. ❌
Perhaps set a static number (like 9 * 4) based on Linux and check for that amount of lines
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We changed it, thanks for the input!
…71-2024-Fall into Assignment9+10
SummarySummary
CoverageAssignment - 91.6%
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great! Looks like you knocked out all the assignment criteria, great code coverage as well! Also nice work on testing for the TaskCanceledException
within the AggregateException
without trying to rethrow.
Partnered with @AustinH5544