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

Expand combinatorial testing of HTTP parser #3166

Merged

Conversation

jonsequitur
Copy link
Contributor

@jonsequitur jonsequitur commented Sep 8, 2023

This PR adds more combinatorial testing and fixes a number of bugs discovered in the process, with scenario-specific tests added in each case. I've removed the HttpBodySeparatorNode concept.

It also contains a few small unrelated changes from API review.

@@ -198,7 +198,8 @@ internal void NormalizeElementKernelNames(KernelInfoCollection kernelInfos)

public string? GetDefaultKernelName()
{
if (TryGetKernelInfoFromMetadata(Metadata, out var kernelInfo))
// FIX: (GetDefaultKernelName) remove from public API
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you intend to leave this change in the current PR?

@jonsequitur jonsequitur force-pushed the combinatorial-testing-for-diagnostics-4 branch from 7ed0728 to ed81852 Compare September 8, 2023 20:43
@@ -74,17 +73,36 @@ public HttpSyntaxTree Parse()

if (ParseRequestSeparator() is { } separatorNode)
{
// FIX: (Parse) uncovered
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this something that will be fixed in a future PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's uncovered but removing it causes tests to fail, which points to a test gap but not to the code being superfluous. We can look into these examples during a group session. (Test-first approaches usually avoid this kind of uncertainty.)

}

return _syntaxTree;
}

private IEnumerable<HttpVariableDeclarationAndAssignmentNode>? ParseVariableDeclarations()
private static void AppendCommentsIfAny(List<HttpCommentNode> commentsToAppend, HttpSyntaxNode prependToNode)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prependToNode -> appendToNode (Or perhaps just change it to node in both functions).

commentsToAppend.Clear();
}

private static void PrependCommentsIfAny(List<HttpCommentNode> commentsToPrepend, HttpSyntaxNode prependToNode)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method looks identical to the one above except for the addBefore argument. Consider creating a single AddCommentsIfAny() method with an addBefore parameter.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method has been removed.


private HttpEmbeddedExpressionNode ParseEmbeddedExpression()
{
var node = new HttpEmbeddedExpressionNode(_sourceText, _syntaxTree);

node.Add(ParseExpressionStart());
node.Add(ParseExpression());
node.Add(ParseExpressionEnd());
var expressionEnd = ParseExpressionEnd();
if (expressionEnd is not null)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious why is there a null check for the end of an expression but not for the expression itself?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found a bug via testing that drove this specific change.

if (IsComment())
{
// FIX: (ParseRequest) this looks suspect... test with a comment at the start of the request node?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this for a future PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potentially, yes. There's no need to hold a PR to fix unrelated pre-existing issues.


while (MoreTokens() && CurrentToken.Kind is not HttpTokenKind.NewLine)
{
ConsumeCurrentTokenInto(node);
}

ParseTrailingWhitespace(node);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider: return PassTRailingWhitespace(node);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was considering removing the return values from these methods as it makes it ambiguous as to whether they return the original node.

return ParseTrailingTrivia(node);
ParseTrailingWhitespace(node);

return node;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider: return PassTRailingWhitespace(node);

@@ -759,15 +772,14 @@ private bool IsComment()
return false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: This line seems redundant since we already return false on line 775 below.

{
if (CurrentToken is { Kind: HttpTokenKind.Punctuation } and { Text: "#" })
if (CurrentToken is { Text: "#" })
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was also a question before the changes in the current PR, but it is unclear whether comments are allowed to start at the end of an existing line e.g.

myHeaderName: myHeaderValue // a comment
or
get https://www.host.com HTTP/1.1 # a comment

I think we disallow this at the moment. But it would be great to add (negative) tests for the above cases. We should probably also report errors like unexpected token "/" at position (*, *) in such cases.

}

var commentsToPrepend = new List<HttpCommentNode>();
if (ParseComment() is { } comment)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we would also fail to parse the comment if there is any whitespace before the # token (since ParseComment expects the current token to be #).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might depend on whether a previous call parsed the trailing whitespace.

For what it's worth, the old parser reports a diagnostic when there's whitespace on the line preceding the #.

@jonsequitur jonsequitur force-pushed the combinatorial-testing-for-diagnostics-4 branch from ba9ae08 to 50f1cb6 Compare September 11, 2023 22:54
Copy link
Contributor

@shyamnamboodiripad shyamnamboodiripad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving to unblock - will complete review later and we can address anything blocking in a follow up PR.

@jonsequitur jonsequitur merged commit c13d287 into dotnet:main Sep 13, 2023
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants