Skip to content

Commit 00a43a1

Browse files
committed
CSHARP-2151: Resync connection string spec tests for percent encoding in userinfo
1 parent 9e163e8 commit 00a43a1

File tree

4 files changed

+43
-55
lines changed

4 files changed

+43
-55
lines changed

src/MongoDB.Driver.Core/Core/Configuration/ConnectionString.cs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ public IReadOnlyList<TagSet> ReadPreferenceTags
365365
{
366366
get { return _readPreferenceTags; }
367367
}
368-
368+
369369
/// <summary>
370370
/// Gets a value indicating whether or not to retry reads.
371371
/// </summary>
@@ -759,6 +759,17 @@ private void Parse()
759759
@"((?<username>[^:@]+)(:(?<password>[^:@]*))?@)?" +
760760
serversPattern + @"(/" + databasePattern + ")?/?" + optionsPattern + "$";
761761

762+
if (_originalConnectionString.Contains("%"))
763+
{
764+
var invalidPercentPattern = @"%$|%.$|%[^0-9a-fA-F]|%[0-9a-fA-F][^0-9a-fA-F]";
765+
if (Regex.IsMatch(_originalConnectionString, invalidPercentPattern))
766+
{
767+
var message = string.Format("The connection string '{0}' contains an invalid '%' escape sequence.",
768+
_originalConnectionString);
769+
throw new MongoConfigurationException(message);
770+
}
771+
}
772+
762773
var match = Regex.Match(_originalConnectionString, pattern);
763774
if (!match.Success)
764775
{
@@ -1111,7 +1122,7 @@ private static TimeSpan ParseTimeSpan(string name, string value)
11111122
}
11121123

11131124
private List<string> GetHostsFromResponse(IDnsQueryResponse response)
1114-
{
1125+
{
11151126
var hosts = new List<string>();
11161127
foreach (var srvRecord in response.Answers.SrvRecords())
11171128
{
@@ -1130,7 +1141,7 @@ private List<string> GetOptionsFromResponse(IDnsQueryResponse response)
11301141
{
11311142
var txtRecords = response.Answers
11321143
.TxtRecords().ToList();
1133-
1144+
11341145
if (txtRecords.Count > 1)
11351146
{
11361147
throw new MongoConfigurationException("Only 1 TXT record is allowed when using the SRV protocol.");

tests/MongoDB.Driver.Core.Tests/Specifications/connection-string/TestRunner.cs

Lines changed: 9 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,17 @@
2828
using MongoDB.Bson.TestHelpers.XunitExtensions;
2929
using Xunit.Sdk;
3030
using System.Collections;
31+
using MongoDB.Bson.TestHelpers.JsonDrivenTests;
3132

3233
namespace MongoDB.Driver.Specifications.connection_string
3334
{
3435
public class TestRunner
3536
{
3637
[SkippableTheory]
3738
[ClassData(typeof(TestCaseFactory))]
38-
public void RunTestDefinition(BsonDocument definition)
39+
public void RunTestDefinition(JsonDrivenTestCase testCase)
3940
{
41+
var definition = testCase.Test;
4042
ConnectionString connectionString = null;
4143
Exception parseException = null;
4244
try
@@ -134,63 +136,19 @@ private EndPoint ConvertExpectedHostToEndPoint(BsonDocument expectedHost)
134136
throw new AssertionException($"Unknown host type {expectedHost["type"]}.");
135137
}
136138

137-
private class TestCaseFactory : IEnumerable<object[]>
139+
private class TestCaseFactory : JsonDrivenTestCaseFactory
138140
{
139141
private static readonly string[] __ignoredTestNames = new string[]
140142
{
141-
"invalid-uris: Missing delimiting slash between hosts and options"
143+
"invalid-uris.json:Missing delimiting slash between hosts and options"
142144
};
143145

144-
public IEnumerator<object[]> GetEnumerator()
145-
{
146-
const string prefix = "MongoDB.Driver.Core.Tests.Specifications.connection_string.tests.";
147-
var executingAssembly = typeof(TestCaseFactory).GetTypeInfo().Assembly;
148-
var enumerable = executingAssembly
149-
.GetManifestResourceNames()
150-
.Where(path => path.StartsWith(prefix) && path.EndsWith(".json"))
151-
.SelectMany(path =>
152-
{
153-
var definition = ReadDefinition(path);
154-
var tests = (BsonArray)definition["tests"];
155-
var fullName = path.Remove(0, prefix.Length);
156-
var list = new List<object[]>();
157-
foreach (BsonDocument test in tests)
158-
{
159-
//var data = new TestCaseData(test);
160-
//data.SetCategory("Specifications");
161-
//data.SetCategory("ConnectionString");
162-
//var testName = fullName.Remove(fullName.Length - 5) + ": " + test["description"];
163-
//if (_ignoredTestNames.Contains(testName))
164-
//{
165-
// data = data.Ignore("Does not apply");
166-
//}
167-
//list.Add(data.SetName(testName));
168-
var testName = fullName.Remove(fullName.Length - 5) + ": " + test["description"];
169-
if (!__ignoredTestNames.Contains(testName))
170-
{
171-
var data = new object[] { test };
172-
list.Add(data);
173-
}
174-
}
175-
return list;
176-
});
177-
return enumerable.GetEnumerator();
178-
}
179-
180-
IEnumerator IEnumerable.GetEnumerator()
181-
{
182-
return GetEnumerator();
183-
}
146+
protected override string PathPrefix => "MongoDB.Driver.Core.Tests.Specifications.connection_string.tests.";
184147

185-
private static BsonDocument ReadDefinition(string path)
148+
protected override IEnumerable<JsonDrivenTestCase> CreateTestCases(BsonDocument document)
186149
{
187-
var executingAssembly = typeof(TestCaseFactory).GetTypeInfo().Assembly;
188-
using (var definitionStream = executingAssembly.GetManifestResourceStream(path))
189-
using (var definitionStringReader = new StreamReader(definitionStream))
190-
{
191-
var definitionString = definitionStringReader.ReadToEnd();
192-
return BsonDocument.Parse(definitionString);
193-
}
150+
return base.CreateTestCases(document)
151+
.Where(test => !__ignoredTestNames.Any(ignoredName => test.Name.EndsWith(ignoredName)));
194152
}
195153
}
196154
}

tests/MongoDB.Driver.Core.Tests/Specifications/connection-string/tests/invalid-uris.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,16 @@
215215
"uri": "mongodb:///tmp/mongodb-27017.sock/",
216216
"valid": false,
217217
"warning": null
218-
}
218+
},
219+
{
220+
"auth": null,
221+
"description": "Username with password containing an unescaped percent sign",
222+
"hosts": null,
223+
"options": null,
224+
"uri": "mongodb://alice%foo:[email protected]",
225+
"valid": false,
226+
"warning": null
227+
}
228+
219229
]
220230
}

tests/MongoDB.Driver.Core.Tests/Specifications/connection-string/tests/invalid-uris.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,3 +191,12 @@ tests:
191191
hosts: ~
192192
auth: ~
193193
options: ~
194+
-
195+
description: "Username with password containing an unescaped percent sign"
196+
uri: "mongodb://alice%foo:[email protected]"
197+
valid: false
198+
warning: ~
199+
hosts: ~
200+
auth: ~
201+
options: ~
202+

0 commit comments

Comments
 (0)