From 3e3a14eafe2e868b1a45c30d67fca4d87b19cea3 Mon Sep 17 00:00:00 2001 From: Kyra Ramesh Krishna Date: Wed, 15 Apr 2026 14:34:34 -0400 Subject: [PATCH 1/6] cover trimstart and trimend in serializer finder switch --- .../SerializerFinderVisitMethodCall.cs | 2 + .../Jira/CSharp5966Tests.cs | 78 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp5966Tests.cs diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/SerializerFinders/SerializerFinderVisitMethodCall.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/SerializerFinders/SerializerFinderVisitMethodCall.cs index 1a704c6a71f..91edc42a9ab 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/SerializerFinders/SerializerFinderVisitMethodCall.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/SerializerFinders/SerializerFinderVisitMethodCall.cs @@ -158,6 +158,8 @@ void DeduceMethodCallSerializers() case "ToList": DeduceToListSerializers(); break; case "ToString": DeduceToStringSerializers(); break; case "Trim": DeduceTrimSerializers(); break; + case "TrimStart": DeduceTrimSerializers(); break; + case "TrimEnd": DeduceTrimSerializers(); break; case "Truncate": DeduceTruncateSerializers(); break; case "Union": DeduceUnionSerializers(); break; case "Week": DeduceWeekSerializers(); break; diff --git a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp5966Tests.cs b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp5966Tests.cs new file mode 100644 index 00000000000..30a0483cf8b --- /dev/null +++ b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp5966Tests.cs @@ -0,0 +1,78 @@ +/* Copyright 2010-present MongoDB Inc. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +using System; +using System.Collections.Generic; +using System.Linq; +using MongoDB.Driver.TestHelpers; +using FluentAssertions; +using Xunit; + +namespace MongoDB.Driver.Tests.Linq.Linq3Implementation.Jira; + +public class CSharp5966Tests : LinqIntegrationTest +{ + public CSharp5966Tests(ClassFixture fixture) + : base(fixture) + { + } + + [Fact] + public void Select_with_TrimStart_should_work() + { + var collection = Fixture.Collection; + + var queryable = collection.AsQueryable() + .Select(x => x.Str.TrimStart(new char[0])); + + var stages = Translate(collection, queryable); + AssertStages(stages, """{ $project : { _v : { $ltrim : { input : "$Str" } }, _id : 0 } }"""); + + var results = queryable.ToList(); + results.Should().Equal("abcd ", "abcd ", "abcd", "abcd"); + } + + [Fact] + public void Select_with_TrimEnd_should_work() + { + var collection = Fixture.Collection; + + var queryable = collection.AsQueryable() + .Select(x => x.Str.TrimEnd(new char[0])); + + var stages = Translate(collection, queryable); + AssertStages(stages, """{ $project : { _v : { $rtrim : { input : "$Str" } }, _id : 0 } }"""); + + var results = queryable.ToList(); + results.Should().Equal(" abcd", "abcd", " abcd", "abcd"); + } + + public class C + { + public int Id { get; set; } + public string Str { get; set; } + } + + public sealed class ClassFixture : MongoCollectionFixture + { + protected override IEnumerable InitialData => + [ + new C { Id = 1, Str = " abcd "}, + new C { Id = 2, Str = "abcd "}, + new C { Id = 3, Str = " abcd"}, + new C { Id = 4, Str = "abcd"}, + ]; + } +} From 6261fc06bb8892067ed36ed2842425c111361ec5 Mon Sep 17 00:00:00 2001 From: Kyra Ramesh Krishna Date: Wed, 15 Apr 2026 14:58:00 -0400 Subject: [PATCH 2/6] cover new trimstart/end in the serializer finder unittests --- .../Linq/Linq3Implementation/SerializerFinders/StringTests.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/StringTests.cs b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/StringTests.cs index d57210ab78b..74498c8d841 100644 --- a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/StringTests.cs +++ b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/StringTests.cs @@ -127,6 +127,8 @@ public void SerializerFinder_should_resolve_string_methods(LambdaExpression expr [TestHelpers.MakeLambda((MyModel model) => model.Name.ToUpperInvariant()), typeof(StringSerializer)], [TestHelpers.MakeLambda((MyModel model) => model.Name.Trim()), typeof(StringSerializer)], [TestHelpers.MakeLambda((MyModel model) => model.Name.Trim(new char[] { ' ' })), typeof(StringSerializer)], + [TestHelpers.MakeLambda((MyModel model) => model.Name.TrimStart(new char[] { ' ' })), typeof(StringSerializer)], + [TestHelpers.MakeLambda((MyModel model) => model.Name.TrimEnd(new char[] { ' ' })), typeof(StringSerializer)], ]; [Theory] From 21fde2422bf4c2d424fead4567aa7446cf2bb4b1 Mon Sep 17 00:00:00 2001 From: Kyra Ramesh Krishna Date: Thu, 16 Apr 2026 10:45:50 -0400 Subject: [PATCH 3/6] address PR --- .../SerializerFinders/SerializerFinderVisitMethodCall.cs | 8 +++++--- .../Linq/Linq3Implementation/Jira/CSharp5966Tests.cs | 1 - .../Linq3Implementation/SerializerFinders/StringTests.cs | 6 ++++++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/SerializerFinders/SerializerFinderVisitMethodCall.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/SerializerFinders/SerializerFinderVisitMethodCall.cs index 91edc42a9ab..9aae17e4f8c 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/SerializerFinders/SerializerFinderVisitMethodCall.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/SerializerFinders/SerializerFinderVisitMethodCall.cs @@ -157,9 +157,11 @@ void DeduceMethodCallSerializers() case "ToHashedIndexKey": DeduceToHashedIndexKeySerializers(); break; case "ToList": DeduceToListSerializers(); break; case "ToString": DeduceToStringSerializers(); break; - case "Trim": DeduceTrimSerializers(); break; - case "TrimStart": DeduceTrimSerializers(); break; - case "TrimEnd": DeduceTrimSerializers(); break; + case "Trim": + case "TrimStart": + case "TrimEnd": + DeduceTrimSerializers(); + break; case "Truncate": DeduceTruncateSerializers(); break; case "Union": DeduceUnionSerializers(); break; case "Week": DeduceWeekSerializers(); break; diff --git a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp5966Tests.cs b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp5966Tests.cs index 30a0483cf8b..7ad55f1fc57 100644 --- a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp5966Tests.cs +++ b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp5966Tests.cs @@ -13,7 +13,6 @@ * limitations under the License. */ -using System; using System.Collections.Generic; using System.Linq; using MongoDB.Driver.TestHelpers; diff --git a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/StringTests.cs b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/StringTests.cs index 74498c8d841..bb714afd53e 100644 --- a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/StringTests.cs +++ b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/SerializerFinders/StringTests.cs @@ -155,6 +155,12 @@ public void SerializerFinder_should_set_unknowable_serializer_for_unsupported_st // StringComparison and CultureInfo overloads are not in ReplaceOverloads [TestHelpers.MakeLambda((MyModel model) => model.Name.Replace("old", "new", StringComparison.Ordinal))], [TestHelpers.MakeLambda((MyModel model) => model.Name.Replace("old", "new", false, CultureInfo.InvariantCulture))], + // Not supported yet, see https://jira.mongodb.org/browse/CSHARP-5979 + [TestHelpers.MakeLambda((MyModel model) => model.Name.Trim(' '))], + [TestHelpers.MakeLambda((MyModel model) => model.Name.TrimStart(' '))], + [TestHelpers.MakeLambda((MyModel model) => model.Name.TrimEnd())], + [TestHelpers.MakeLambda((MyModel model) => model.Name.TrimStart())], + [TestHelpers.MakeLambda((MyModel model) => model.Name.TrimEnd())], #endif ]; From 484ed0c381557bd18b9ec70551de3bd7f048d3cd Mon Sep 17 00:00:00 2001 From: Kyra Ramesh Krishna Date: Thu, 16 Apr 2026 14:40:47 -0400 Subject: [PATCH 4/6] move tests from jira ticket file to it's own file in the integration folder --- .../Linq/Integration/TrimTests.cs | 155 ++++++++++++++++++ .../Jira/CSharp5966Tests.cs | 77 --------- 2 files changed, 155 insertions(+), 77 deletions(-) create mode 100644 tests/MongoDB.Driver.Tests/Linq/Integration/TrimTests.cs delete mode 100644 tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp5966Tests.cs diff --git a/tests/MongoDB.Driver.Tests/Linq/Integration/TrimTests.cs b/tests/MongoDB.Driver.Tests/Linq/Integration/TrimTests.cs new file mode 100644 index 00000000000..4f29cf2a16a --- /dev/null +++ b/tests/MongoDB.Driver.Tests/Linq/Integration/TrimTests.cs @@ -0,0 +1,155 @@ +/* Copyright 2010-present MongoDB Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System.Collections.Generic; +using System.Linq; +using MongoDB.Driver.TestHelpers; +using FluentAssertions; +using Xunit; + +namespace MongoDB.Driver.Tests.Linq.Integration; + +public class TrimTests : LinqIntegrationTest +{ + public TrimTests(ClassFixture fixture) + : base(fixture) + { + } + + [Fact] + public void Select_with_Trim_should_work() + { + var collection = Fixture.Collection; + + var queryable = collection.AsQueryable() + .Select(x => x.Str.Trim()); + + var stages = Translate(collection, queryable); + AssertStages(stages, """{ $project : { _v : { $trim : { input : "$Str" } }, _id : 0 } }"""); + + var results = queryable.ToList(); + results.Should().Equal("abcd", "abcd", "abcd", "abcd"); + } + + [Fact] + public void Select_with_Trim_with_chars_should_work() + { + var collection = Fixture.Collection; + + var queryable = collection.AsQueryable() + .Select(x => x.Str.Trim(new[] { ' ', 'a' })); + + var stages = Translate(collection, queryable); + AssertStages(stages, """{ $project : { _v : { $trim : { input : "$Str", chars : " a" } }, _id : 0 } }"""); + + var results = queryable.ToList(); + results.Should().Equal("bcd", "bcd", "bcd", "bcd"); + } + + [Fact] + public void Select_with_Trim_with_empty_chars_should_work() + { + var collection = Fixture.Collection; + + var queryable = collection.AsQueryable() + .Select(x => x.Str.Trim(new char[0])); + + var stages = Translate(collection, queryable); + AssertStages(stages, """{ $project : { _v : { $trim : { input : "$Str" } }, _id : 0 } }"""); + + var results = queryable.ToList(); + results.Should().Equal("abcd", "abcd", "abcd", "abcd"); + } + + [Fact] + public void Select_with_TrimStart_with_chars_should_work() + { + var collection = Fixture.Collection; + + var queryable = collection.AsQueryable() + .Select(x => x.Str.TrimStart(new[] { ' ', 'a' })); + + var stages = Translate(collection, queryable); + AssertStages(stages, """{ $project : { _v : { $ltrim : { input : "$Str", chars : " a" } }, _id : 0 } }"""); + + var results = queryable.ToList(); + results.Should().Equal("bcd ", "bcd ", "bcd", "bcd"); + } + + [Fact] + public void Select_with_TrimStart_with_empty_chars_should_work() + { + var collection = Fixture.Collection; + + var queryable = collection.AsQueryable() + .Select(x => x.Str.TrimStart(new char[0])); + + var stages = Translate(collection, queryable); + AssertStages(stages, """{ $project : { _v : { $ltrim : { input : "$Str" } }, _id : 0 } }"""); + + var results = queryable.ToList(); + results.Should().Equal("abcd ", "abcd ", "abcd", "abcd"); + } + + [Fact] + public void Select_with_TrimEnd_with_chars_should_work() + { + var collection = Fixture.Collection; + + var queryable = collection.AsQueryable() + .Select(x => x.Str.TrimEnd(new[] { ' ', 'd' })); + + var stages = Translate(collection, queryable); + AssertStages(stages, """{ $project : { _v : { $rtrim : { input : "$Str", chars : " d" } }, _id : 0 } }"""); + + var results = queryable.ToList(); + results.Should().Equal(" abc", "abc", " abc", "abc"); + } + + [Fact] + public void Select_with_TrimEnd_with_empty_chars_should_work() + { + var collection = Fixture.Collection; + + var queryable = collection.AsQueryable() + .Select(x => x.Str.TrimEnd(new char[0])); + + var stages = Translate(collection, queryable); + AssertStages(stages, """{ $project : { _v : { $rtrim : { input : "$Str" } }, _id : 0 } }"""); + + var results = queryable.ToList(); + results.Should().Equal(" abcd", "abcd", " abcd", "abcd"); + } + + // TODO CSHARP-5979: Add coverage for parameterless and single char overloads of Trim, TrimStart, and TrimEnd. + // e.g. Trim(' '), TrimStart(), TrimStart(' '), TrimEnd(), TrimEnd(' ') + + public class C + { + public int Id { get; set; } + public string Str { get; set; } + } + + public sealed class ClassFixture : MongoCollectionFixture + { + protected override IEnumerable InitialData => + [ + new C { Id = 1, Str = " abcd "}, + new C { Id = 2, Str = "abcd "}, + new C { Id = 3, Str = " abcd"}, + new C { Id = 4, Str = "abcd"}, + ]; + } +} diff --git a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp5966Tests.cs b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp5966Tests.cs deleted file mode 100644 index 7ad55f1fc57..00000000000 --- a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp5966Tests.cs +++ /dev/null @@ -1,77 +0,0 @@ -/* Copyright 2010-present MongoDB Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System.Collections.Generic; -using System.Linq; -using MongoDB.Driver.TestHelpers; -using FluentAssertions; -using Xunit; - -namespace MongoDB.Driver.Tests.Linq.Linq3Implementation.Jira; - -public class CSharp5966Tests : LinqIntegrationTest -{ - public CSharp5966Tests(ClassFixture fixture) - : base(fixture) - { - } - - [Fact] - public void Select_with_TrimStart_should_work() - { - var collection = Fixture.Collection; - - var queryable = collection.AsQueryable() - .Select(x => x.Str.TrimStart(new char[0])); - - var stages = Translate(collection, queryable); - AssertStages(stages, """{ $project : { _v : { $ltrim : { input : "$Str" } }, _id : 0 } }"""); - - var results = queryable.ToList(); - results.Should().Equal("abcd ", "abcd ", "abcd", "abcd"); - } - - [Fact] - public void Select_with_TrimEnd_should_work() - { - var collection = Fixture.Collection; - - var queryable = collection.AsQueryable() - .Select(x => x.Str.TrimEnd(new char[0])); - - var stages = Translate(collection, queryable); - AssertStages(stages, """{ $project : { _v : { $rtrim : { input : "$Str" } }, _id : 0 } }"""); - - var results = queryable.ToList(); - results.Should().Equal(" abcd", "abcd", " abcd", "abcd"); - } - - public class C - { - public int Id { get; set; } - public string Str { get; set; } - } - - public sealed class ClassFixture : MongoCollectionFixture - { - protected override IEnumerable InitialData => - [ - new C { Id = 1, Str = " abcd "}, - new C { Id = 2, Str = "abcd "}, - new C { Id = 3, Str = " abcd"}, - new C { Id = 4, Str = "abcd"}, - ]; - } -} From 080a44b512864d6d7731b198c278099499f0407f Mon Sep 17 00:00:00 2001 From: Kyra Ramesh Krishna Date: Fri, 17 Apr 2026 16:17:11 -0400 Subject: [PATCH 5/6] rename to StringTrimTests and add preprocessor directive for newer trim methods --- .../Linq/Integration/{TrimTests.cs => StringTrimTests.cs} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename tests/MongoDB.Driver.Tests/Linq/Integration/{TrimTests.cs => StringTrimTests.cs} (97%) diff --git a/tests/MongoDB.Driver.Tests/Linq/Integration/TrimTests.cs b/tests/MongoDB.Driver.Tests/Linq/Integration/StringTrimTests.cs similarity index 97% rename from tests/MongoDB.Driver.Tests/Linq/Integration/TrimTests.cs rename to tests/MongoDB.Driver.Tests/Linq/Integration/StringTrimTests.cs index 4f29cf2a16a..1b45bb8ccae 100644 --- a/tests/MongoDB.Driver.Tests/Linq/Integration/TrimTests.cs +++ b/tests/MongoDB.Driver.Tests/Linq/Integration/StringTrimTests.cs @@ -21,9 +21,9 @@ namespace MongoDB.Driver.Tests.Linq.Integration; -public class TrimTests : LinqIntegrationTest +public class StringTrimTests : LinqIntegrationTest { - public TrimTests(ClassFixture fixture) + public StringTrimTests(ClassFixture fixture) : base(fixture) { } From e7aad211136bf73a66b24d15ce4622b2d9dda225 Mon Sep 17 00:00:00 2001 From: Kyra Ramesh Krishna Date: Fri, 17 Apr 2026 17:02:35 -0400 Subject: [PATCH 6/6] wrap the not supported test itself in if / endif --- tests/MongoDB.Driver.Tests/Linq/Integration/StringTrimTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/MongoDB.Driver.Tests/Linq/Integration/StringTrimTests.cs b/tests/MongoDB.Driver.Tests/Linq/Integration/StringTrimTests.cs index 1b45bb8ccae..d74e7977027 100644 --- a/tests/MongoDB.Driver.Tests/Linq/Integration/StringTrimTests.cs +++ b/tests/MongoDB.Driver.Tests/Linq/Integration/StringTrimTests.cs @@ -133,7 +133,7 @@ public void Select_with_TrimEnd_with_empty_chars_should_work() results.Should().Equal(" abcd", "abcd", " abcd", "abcd"); } - // TODO CSHARP-5979: Add coverage for parameterless and single char overloads of Trim, TrimStart, and TrimEnd. + // Add coverage for parameterless and single char overloads of Trim, TrimStart, and TrimEnd, see https://jira.mongodb.org/browse/CSHARP-5979 // e.g. Trim(' '), TrimStart(), TrimStart(' '), TrimEnd(), TrimEnd(' ') public class C