public async Task CompositeUrlParamInjectionTest()
        {
            var client = await LoginTask()
                         .ConfigureAwait(false);

            await DeleteTestingRecords(client)
            .ConfigureAwait(false);

            try
            {
                var request = new CompositeRequest(true);
                request.Create("create", "Product2", Dnf.Assign(GetTestProduct2(), new JObject
                {
                    ["Name"]            = "UnitTest' AND Name != '",
                    ["ProductCode"]     = "UnitTest' AND Name != '",
                    ["CurrencyIsoCode"] = "USD"
                }));
                request.Query("query", @"
SELECT Id, Name, ProductCode FROM Product2 WHERE Id = '@{create.id}'");
                request.Query("query2", @"
SELECT Id, Name, ProductCode FROM Product2
WHERE Id = '@{query.records[0].Id}'
AND ProductCode = '@{query.records[0].ProductCode}'");
                request.Update("update", "Product2", new JObject
                {
                    ["Id"]          = "@{query.records[0].Id}",
                    ["ProductCode"] = "@{query.records[0].ProductCode}2"
                });
                request.Query("updated", $@"
SELECT Id, Name, ProductCode FROM Product2
WHERE Id = '@{{query.records[0].Id}}'
AND ProductCode = {Dnf.SoqlString("UnitTest' AND Name != '2")}");
                //request.UpsertExternal("upsert", "Product2", "Id", "@{updated.records[0].Id}' AND Name != '2", new JObject
                //{
                //    ["Name"] = "@{query.records[0].Name}"
                //});
                request.Delete("delete", "Product2", "@{updated.records[0].Id}");
                var result = await client.Composite.PostAsync(request)
                             .ConfigureAwait(false);

                result.Assert();
                Assert.Equal(0, result.Queries("query2").TotalSize);
            }
            finally
            {
                await DeleteTestingRecords(client)
                .ConfigureAwait(false);
            }
        }
        public async Task CompositeFailTest()
        {
            var client = await LoginTask()
                         .ConfigureAwait(false);

            // characters to avoid
            // & break query string i.e. q=... MALFORMED_QUERY
            // + break query string, my guess: converted to space
            // ' upsert failed, not found
            // / upsert failed, not found
            // % transaction all rollback
            // \ transaction all rollback
            // $ transaction all rollback


            await Assert.ThrowsAsync <ForceException>(async() =>
            {
                const string testName = "UnitTest$@\\/ %!~-[].,()`=&+*_\"'{}";

                var request = new CompositeRequest(true);
                request.Create("create", "Case", new JObject
                {
                    ["Subject"] = $"{testName}"
                });
                request.Query("query1", $@"
SELECT Id, Subject
FROM Case
WHERE Id = '@{{create.id}}'
AND Subject = {Dnf.SoqlString($"{testName}")}");
                request.Update("update", "Case", new JObject
                {
                    ["Id"]      = "@{create.id}",
                    ["Subject"] = $"UnitTest{testName}"
                });
                request.Query("query2", $@"
SELECT Id, Subject
FROM Case
WHERE Id = '@{{create.id}}'
AND Subject = {Dnf.SoqlString($"UnitTest{testName}")}");
                request.UpsertExternal("upsert", "Case", "Id", new JObject
                {
                    ["Id"]      = "@{query.records[0].Id}",
                    ["Subject"] = $"UnitTest {testName}"
                });
                request.Query("query3", $@"
SELECT Id, Subject
FROM Case
WHERE Id = '@{{create.id}}'
AND Subject = {Dnf.SoqlString($"UnitTest {testName}")}");
                request.Delete("delete", "Case", "1@{query2.records[0].Id}");
                var result = await client.Composite.PostAsync(request)
                             .ConfigureAwait(false);
                WriteLine(result.ToString());
                Assert.NotNull(result.Errors("query3"));
                Assert.Equal(
                    result.Requests().Count - 1,
                    result.Errors().Values
                    .Count(errs => errs.Any(err => err.Message == "The transaction was rolled back since another operation in the same transaction failed.")));
                result.Assert();
            })
            .ConfigureAwait(false);
        }
        public async Task CompositeSoqlInjectionTest()
        {
            var client = await LoginTask()
                         .ConfigureAwait(false);

            await DeleteTestingRecords(client)
            .ConfigureAwait(false);

            try
            {
                const string testText = "UnitTest' AND Name != '";
                var          request  = new CompositeRequest();
                request.Create("create", "Product2", Dnf.Assign(GetTestProduct2(), new JObject
                {
                    ["ProductCode"] = testText
                }));
                request.Retrieve("created", "Product2", "@{create.id}");

                request.Query("query", @"
SELECT Id, Name, ProductCode FROM Product2 WHERE Id = '@{created.Id}'
AND ProductCode = '@{created.ProductCode}'");

                request.UpsertExternal("upsert", "Product2", "Id", "@{created.Id}", new JObject
                {
                    ["Name"] = testText
                });
                request.Query("upserted", $@"
SELECT Id, Name, ProductCode FROM Product2 WHERE Id = '@{{created.Id}}'
AND Name = {Dnf.SoqlString(testText)}");

                request.Update("update", "Product2", new JObject
                {
                    ["Id"]          = "@{created.Id}",
                    ["ProductCode"] = "@{created.ProductCode}"
                });
                request.Query("updated", $@"
SELECT Id, Name, ProductCode FROM Product2 WHERE Id = '@{{created.Id}}'
AND ProductCode = {Dnf.SoqlString(testText)}");

                request.Delete("delete", "Product2", "@{create.id}");
                var result = await client.Composite.PostAsync(request)
                             .ConfigureAwait(false);

                result.Assert();
                Assert.Equal(testText, result.Results("created")["ProductCode"]);
                Assert.Equal(0, result.Queries("query").TotalSize);
                Assert.Equal(testText, result.Queries("upserted").Records?[0]["Name"]);
                Assert.Equal(testText.Replace("\n", " ").Replace("\\", ""), result.Queries("updated").Records?[0]["Name"]);
            }
            finally
            {
                await DeleteTestingRecords(client)
                .ConfigureAwait(false);
            }
            try
            {
                const string testText = "Uni\\nt\\tTe\\\\ns\\\\ts\\\\\\nt\\\\\\tt";
                var          request  = new CompositeRequest();
                request.Create("create", "Product2", Dnf.Assign(GetTestProduct2(), new JObject
                {
                    ["ProductCode"] = testText
                }));
                request.Retrieve("created", "Product2", "@{create.id}");

                request.Query("query", @"
SELECT Id, Name, ProductCode FROM Product2 WHERE Id = '@{created.Id}'
AND ProductCode = '@{created.ProductCode}'");

                // cannot upsert
                request.UpsertExternal("upsert", "Product2", "Id", "@{created.Id}", new JObject
                {
                    ["Name"] = testText
                });
                request.Query("upserted", $@"
SELECT Id, Name, ProductCode FROM Product2 WHERE Id = '@{{created.Id}}'
AND Name = {Dnf.SoqlString(testText)}");

                request.Update("update", "Product2", new JObject
                {
                    ["Id"]          = "@{created.Id}",
                    ["ProductCode"] = "@{created.ProductCode}"
                });
                request.Retrieve("updated", "Product2", "@{created.Id}");

                request.Delete("delete", "Product2", "@{create.id}");
                var result = await client.Composite.PostAsync(request)
                             .ConfigureAwait(false);

                //result.Assert();
                Assert.Equal(testText, result.Results("created")["ProductCode"]);
                Assert.Equal(0, result.Queries("query").TotalSize);
                Assert.Equal(1, result.Queries("upserted").TotalSize);
                Assert.Equal("Uni t\tTe\\ns\\ts\\ t\\\tt", (string)result.Results("updated")["ProductCode"]);
            }
            finally
            {
                await DeleteTestingRecords(client)
                .ConfigureAwait(false);
            }
        }