diff --git a/src/SqlClient.DesignTime/DesignTimeConnectionString.fs b/src/SqlClient.DesignTime/DesignTimeConnectionString.fs index d5ca594a..1dcf8a4f 100644 --- a/src/SqlClient.DesignTime/DesignTimeConnectionString.fs +++ b/src/SqlClient.DesignTime/DesignTimeConnectionString.fs @@ -12,7 +12,9 @@ type internal DesignTimeConnectionString = | NameInConfig of name: string * value: string * provider: string static member Parse(s: string, resolutionFolder, fileName) = - match s.Trim().Split([|'='|], 2, StringSplitOptions.RemoveEmptyEntries) with + // Use StringSplitOptions.None so that the empty-string guard actually fires: + // RemoveEmptyEntries turns "" into [||] which skips the [|""|] branch. + match s.Trim().Split([|'='|], 2, StringSplitOptions.None) with | [| "" |] -> invalidArg "ConnectionStringOrName" "Value is empty!" | [| prefix; tail |] when prefix.Trim().ToLower() = "name" -> let name = tail.Trim() diff --git a/tests/SqlClient.DesignTime.Tests/DesignTimeConnectionStringTests.fs b/tests/SqlClient.DesignTime.Tests/DesignTimeConnectionStringTests.fs index d26ecda1..9b3d233b 100644 --- a/tests/SqlClient.DesignTime.Tests/DesignTimeConnectionStringTests.fs +++ b/tests/SqlClient.DesignTime.Tests/DesignTimeConnectionStringTests.fs @@ -28,3 +28,37 @@ let RuntimeConfig() = let x = DesignTimeConnectionString.Parse("name=AdventureWorks", __SOURCE_DIRECTORY__, "app.config") let actual = Linq.RuntimeHelpers.LeafExpressionConverter.EvaluateQuotation( x.RunTimeValueExpr(isHostedExecution = false)) |> unbox Assert.Equal( adventureWorks, actual) + +// ---- Edge case tests for Parse ---- + +[] +let ``Empty string throws ArgumentException`` () = + // The [| "" |] guard in Parse must fire — not be skipped by RemoveEmptyEntries. + Assert.Throws( + fun () -> DesignTimeConnectionString.Parse("", resolutionFolder = "", fileName = "") |> box + ) |> ignore + +[] +let ``Whitespace-only string throws ArgumentException`` () = + Assert.Throws( + fun () -> DesignTimeConnectionString.Parse(" ", resolutionFolder = "", fileName = "") |> box + ) |> ignore + +[] +let ``Literal connection string is parsed correctly`` () = + let cs = "Data Source=.;Initial Catalog=Test;Integrated Security=True" + let x = DesignTimeConnectionString.Parse(cs, resolutionFolder = "", fileName = "") + match x with + | Literal value -> Assert.Equal(cs, value) + | _ -> failwith "Expected Literal" + +[] +let ``Literal IsDefinedByLiteral is true`` () = + let x = DesignTimeConnectionString.Parse("Server=.;Database=Test", resolutionFolder = "", fileName = "") + Assert.True(x.IsDefinedByLiteral) + +[] +let ``Literal Value returns the connection string`` () = + let cs = "Server=.;Database=Northwind" + let x = DesignTimeConnectionString.Parse(cs, resolutionFolder = "", fileName = "") + Assert.Equal(cs, x.Value)