示例#1
0
        public async Task DisposedTransactionDoesntLeak()
        {
            // This test ensures that a transaction that had neither commit nor rollback called does
            // not leak its transaction state to a subsequent transaction.
            // The way this works currently is that every session added to the pool gets its state cleared.
            // The reserved session in SpannerConnection can only be used for readonly transactions and is
            // therefore immune to this bug.  However if that every changes, this test will catch it.
            using (var connection = _fixture.GetConnection())
            {
                connection.Open();
                // The following line increments by one, but never commits the transaction, allowing it
                // to get disposed (which releases the session).
                await IncrementByOneAsync(connection, true);

                await RetryHelpers.ExecuteWithRetryAsync(async() =>
                {
                    using (var tx = await connection.BeginTransactionAsync())
                    {
                        // Because Cloud Spanner does not have "read your writes"
                        // to test any leaks, we must commit the transaction and then read it.
                        await tx.CommitAsync();
                    }
                });

                // The value should not be present in the table.
                using (var cmd = connection.CreateSelectCommand($"SELECT Int64Value FROM {_fixture.TableName} WHERE K=@k"))
                {
                    cmd.Parameters.Add("k", SpannerDbType.String, _key);
                    Assert.Equal(DBNull.Value, await cmd.ExecuteScalarAsync().ConfigureAwait(false));
                }
            }
        }
        public void AdapterUpdate()
        {
            RetryHelpers.RetryOnce(() =>
            {
                using (var connection = _fixture.GetConnection())
                {
                    var adapter = new SpannerDataAdapter(connection, _fixture.TableName, "Key");

                    //Load
                    var testDataSet = new DataSet();
                    adapter.Fill(testDataSet);

                    //update, reload
                    var newValue = Guid.NewGuid().ToString();
                    var oldKey   = testDataSet.Tables[0].Rows[1]["Key"];
                    testDataSet.Tables[0].Rows[1]["StringValue"] = newValue;
                    adapter.Update(testDataSet);
                    testDataSet.Clear();
                    adapter.Fill(testDataSet);
                    int i = 0;
                    for (; i < testDataSet.Tables[0].Rows.Count; i++)
                    {
                        if (testDataSet.Tables[0].Rows[i]["Key"].Equals(oldKey))
                        {
                            break;
                        }
                    }
                    var row = testDataSet.Tables[0].Rows.Cast <DataRow>()
                              .FirstOrDefault(r => r["Key"].Equals(oldKey));
                    Assert.NotNull(row);
                    Assert.Equal(newValue, row["StringValue"]);
                }
            });
        }
示例#3
0
        public void MultiTableWrite()
        {
            // For simplicity, use a new key so that this test is entirely self-contained.
            string key = IdGenerator.FromGuid();

            RetryHelpers.ExecuteWithRetry(() =>
            {
                using (var connection = _fixture.GetConnection())
                {
                    connection.Open();
                    using (var transaction = connection.BeginTransaction())
                    {
                        using (var cmd1 = connection.CreateInsertCommand(_fixture.TableName))
                        {
                            cmd1.Transaction = transaction;
                            cmd1.Parameters.Add("K", SpannerDbType.String).Value           = key;
                            cmd1.Parameters.Add("StringValue", SpannerDbType.String).Value = "text";
                            cmd1.ExecuteNonQuery();
                        }

                        using (var cmd2 = connection.CreateInsertCommand(_fixture.TableName2))
                        {
                            cmd2.Transaction = transaction;
                            cmd2.Parameters.Add("K", SpannerDbType.String).Value         = key;
                            cmd2.Parameters.Add("Int64Value", SpannerDbType.Int64).Value = 50;
                            cmd2.ExecuteNonQuery();
                        }

                        // Commit mutations from both commands, atomically.
                        transaction.Commit();
                    }
                }
            });

            // Read the values from both tables
            using (var connection = _fixture.GetConnection())
            {
                using (var command = connection.CreateSelectCommand($"SELECT * FROM {_fixture.TableName} WHERE K=@Key"))
                {
                    command.Parameters.Add("Key", SpannerDbType.String).Value = key;
                    using (var reader = command.ExecuteReader())
                    {
                        Assert.True(reader.Read());
                        Assert.Equal("text", reader["StringValue"]);
                        Assert.False(reader.Read());
                    }
                }

                using (var command = connection.CreateSelectCommand($"SELECT * FROM {_fixture.TableName2} WHERE K=@Key"))
                {
                    command.Parameters.Add("Key", SpannerDbType.String).Value = key;
                    using (var reader = command.ExecuteReader())
                    {
                        Assert.True(reader.Read());
                        Assert.Equal(50L, reader["Int64Value"]);
                        Assert.False(reader.Read());
                    }
                }
            }
        }
        /// <summary>
        /// Each test is able to use a different set of rows, varied by key value K.
        /// This method creates the rows with a random K and returns K.
        /// </summary>
        public string CreateTestRows([CallerMemberName] string testName = null)
        {
            string key = $"{testName} - {Guid.NewGuid()}";

            Insert(0, false, false, false);
            Insert(1, true, false, false);
            Insert(2, false, true, false);
            Insert(3, false, false, true);
            Insert(4, true, true, true);

            void Insert(int value, bool update, bool delete, bool copy)
            {
                RetryHelpers.ExecuteWithRetry(() =>
                {
                    using (var connection = GetConnection())
                    {
                        using (var command = connection.CreateInsertCommand(TableName))
                        {
                            command.Parameters.Add("Key", SpannerDbType.String, key);
                            command.Parameters.Add("OriginalValue", SpannerDbType.Int64, value);
                            command.Parameters.Add("Value", SpannerDbType.Int64, value);
                            command.Parameters.Add("UpdateMe", SpannerDbType.Bool, update);
                            command.Parameters.Add("DeleteMe", SpannerDbType.Bool, delete);
                            command.Parameters.Add("CopyMe", SpannerDbType.Bool, copy);
                            RetryHelpers.ExecuteWithRetry(() => command.ExecuteNonQuery());
                        }
                    }
                });
            }

            return(key);
        }
        public void AdapterDeleteInsert()
        {
            RetryHelpers.RetryOnce(() =>
            {
                using (var connection = _fixture.GetConnection())
                {
                    var adapter = new SpannerDataAdapter(connection, _fixture.TableName, "Key");

                    //Load
                    var testDataSet = new DataSet();
                    adapter.Fill(testDataSet);
                    var k0           = testDataSet.Tables[0].Rows[0]["Key"];
                    var stringValue0 = testDataSet.Tables[0].Rows[0]["StringValue"];
                    Assert.IsType <string>(k0);
                    Assert.IsType <string>(stringValue0);

                    //Delete, reload
                    testDataSet.Tables[0].Rows[0].Delete();
                    adapter.Update(testDataSet);
                    testDataSet.Clear();
                    adapter.Fill(testDataSet);
                    Assert.Equal(_fixture.RowCount - 1, testDataSet.Tables[0].Rows.Count);

                    //insert, reload
                    var newRow            = testDataSet.Tables[0].NewRow();
                    newRow["Key"]         = k0;
                    newRow["StringValue"] = stringValue0;
                    testDataSet.Tables[0].Rows.Add(newRow);
                    adapter.Update(testDataSet);
                    testDataSet.Clear();
                    adapter.Fill(testDataSet);
                    Assert.Equal(_fixture.RowCount, testDataSet.Tables[0].Rows.Count);
                }
            });
        }
        public void AdapterOverrideSelect()
        {
            RetryHelpers.RetryOnce(() =>
            {
                using (var connection = _fixture.GetConnection())
                {
                    var adapter = new SpannerDataAdapter(connection, _fixture.TableName, "Key")
                    {
                        SelectCommand =
                            connection.CreateSelectCommand(
                                $"SELECT * FROM {_fixture.TableName} WHERE Key='k2'")
                    };

                    //Load
                    var testDataSet = new DataSet();
                    adapter.Fill(testDataSet);
                    Assert.Equal(1, testDataSet.Tables[0].Rows.Count);

                    //update, reload (update still works even with an overloaded selectcommand)
                    string newValue = Guid.NewGuid().ToString();
                    testDataSet.Tables[0].Rows[0]["StringValue"] = newValue;
                    adapter.Update(testDataSet);
                    testDataSet.Clear();
                    adapter.Fill(testDataSet);
                    Assert.Equal(newValue, testDataSet.Tables[0].Rows[0]["StringValue"]);
                }
            });
        }
示例#7
0
        protected override void PopulateTable(bool fresh)
        {
            // If we're using an old table, assume that the data is okay.
            if (!fresh)
            {
                return;
            }
            using (var connection = GetConnection())
            {
                connection.Open();
                RetryHelpers.ExecuteWithRetry(() =>
                {
                    using (var tx = connection.BeginTransaction())
                    {
                        var cmd                  = connection.CreateInsertCommand(TableName);
                        var keyParameter         = cmd.Parameters.Add("Key", SpannerDbType.String);
                        var stringValueParameter = cmd.Parameters.Add("StringValue", SpannerDbType.String);
                        var int64ValueParameter  = cmd.Parameters.Add("Int64Value", SpannerDbType.Int64);
                        cmd.Transaction          = tx;

                        for (var i = 0; i < RowCount; i++)
                        {
                            keyParameter.Value         = "k" + i;
                            stringValueParameter.Value = "v" + i;
                            int64ValueParameter.Value  = i;
                            cmd.ExecuteNonQuery();
                        }

                        tx.Commit();
                    }
                });
            }
        }
示例#8
0
        public async Task BaselineTest(SharedFxConfig config)
        {
            var previousVersion       = TestData.GetPreviousAspNetCoreReleaseVersion();
            var url                   = new Uri($"https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/Runtime/" + previousVersion + "/aspnetcore-runtime-internal-" + previousVersion + "-win-x64.zip");
            var zipName               = "assemblies.zip";
            var nugetAssemblyVersions = new Dictionary <string, Version>();
            var dir                   = TestData.GetTestDataValue($"RuntimeAssetsOutputPath:{config.Name}");

            using (var testClient = new WebClient())
            {
                var reporter = new ConsoleReporter(PhysicalConsole.Singleton);
                await RetryHelpers.RetryAsync(async() => await testClient.DownloadFileTaskAsync(url, zipName), reporter);
            }

            var zipPath           = Path.Combine(AppContext.BaseDirectory, zipName);
            var tempDirectoryPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());

            try
            {
                Directory.CreateDirectory(tempDirectoryPath);
                ZipFile.ExtractToDirectory(zipPath, tempDirectoryPath);
                var nugetAssembliesPath = Path.Combine(tempDirectoryPath, "shared", config.Name, previousVersion);


                var files = Directory.GetFiles(nugetAssembliesPath, "*.dll");
                foreach (var file in files)
                {
                    try
                    {
                        var assemblyVersion = AssemblyName.GetAssemblyName(file).Version;
                        var dllName         = Path.GetFileName(file);
                        nugetAssemblyVersions.Add(dllName, assemblyVersion);
                    }
                    catch (BadImageFormatException) { }
                }

                files = Directory.GetFiles(dir, "*.dll");

                Assert.All(files, file =>
                {
                    try
                    {
                        var localAssemblyVersion = AssemblyName.GetAssemblyName(file).Version;
                        var dllName = Path.GetFileName(file);
                        Assert.Contains(dllName, nugetAssemblyVersions.Keys);
                        Assert.InRange(localAssemblyVersion.CompareTo(nugetAssemblyVersions[dllName]), 0, int.MaxValue);
                    }
                    catch (BadImageFormatException) { }
                });
            }
            finally
            {
                Directory.Delete(tempDirectoryPath, true);
            }
        }
        protected override void PopulateTable(bool fresh)
        {
            // Assume old data is still valid
            if (!fresh)
            {
                return;
            }
            const int PartitionSize = 5000;

            using (var connection = GetConnection())
            {
                connection.Open();
                for (var i = 0; i < NumPartitionReadRows / PartitionSize; i++)
                {
                    RetryHelpers.RetryOnce(() =>
                    {
                        using (var tx = connection.BeginTransaction())
                        {
                            using (var cmd = connection.CreateInsertCommand(TableName))
                            {
                                var idParameter      = cmd.Parameters.Add("OrderId", SpannerDbType.String);
                                var dateParameter    = cmd.Parameters.Add("OrderDate", SpannerDbType.Timestamp);
                                var productParameter = cmd.Parameters.Add("Product", SpannerDbType.String);
                                cmd.Transaction      = tx;
                                DateTime now         = DateTime.UtcNow;
                                for (var x = 1; x < PartitionSize; x++)
                                {
                                    idParameter.Value      = IdGenerator.FromGuid();
                                    dateParameter.Value    = now.AddDays(-x);
                                    productParameter.Value = $"Widget#{x}";
                                    cmd.ExecuteNonQuery();
                                }
                                tx.Commit();
                            }
                        }
                    });
                }
            }
        }
        protected override void PopulateTable(bool fresh)
        {
            // If we're using an old table, assume that the data is okay.
            if (!fresh)
            {
                return;
            }

            using (var connection = GetConnection())
            {
                connection.Open();
                Assert.True(connection.IsOpen);
                RetryHelpers.ExecuteWithRetry(() =>
                {
                    using (var tx = connection.BeginTransaction())
                    {
                        var cmd            = connection.CreateInsertCommand(TableName);
                        var keyParameter   = cmd.Parameters.Add("Key", SpannerDbType.String);
                        var valueParameter = cmd.Parameters.Add("StringValue", SpannerDbType.String);

                        cmd.Transaction = tx;

                        for (var i = 0; i < RowCount - 1; ++i)
                        {
                            keyParameter.Value   = "k" + i;
                            valueParameter.Value = "v" + i;
                            cmd.ExecuteNonQuery();
                        }

                        // And one extra row, with a null value.
                        keyParameter.Value   = "kNull";
                        valueParameter.Value = DBNull.Value;
                        cmd.ExecuteNonQuery();

                        tx.Commit();
                    }
                });
            }
        }
示例#11
0
        public async Task ReturnCommitStats()
        {
            Skip.If(_fixture.RunningOnEmulator, "Emulator does not yet support CommitStats");
            CommitStatsCapturerLogger logger = new CommitStatsCapturerLogger();
            string key = IdGenerator.FromGuid();
            await RetryHelpers.ExecuteWithRetryAsync(async() =>
            {
                using (var connection = _fixture.GetConnection(logger))
                {
                    await connection.OpenAsync();
                    using (var transaction = connection.BeginTransaction())
                    {
                        transaction.LogCommitStats = true;
                        using (var cmd1 = connection.CreateInsertCommand(_fixture.TableName))
                        {
                            cmd1.Transaction = transaction;
                            cmd1.Parameters.Add("K", SpannerDbType.String).Value           = key;
                            cmd1.Parameters.Add("StringValue", SpannerDbType.String).Value = "text";
                            await cmd1.ExecuteNonQueryAsync();
                        }

                        using (var cmd2 = connection.CreateInsertCommand(_fixture.TableName2))
                        {
                            cmd2.Transaction = transaction;
                            cmd2.Parameters.Add("K", SpannerDbType.String).Value         = key;
                            cmd2.Parameters.Add("Int64Value", SpannerDbType.Int64).Value = 50;
                            await cmd2.ExecuteNonQueryAsync();
                        }

                        await transaction.CommitAsync();
                        // MutationCount == 4, as we inserted 2 rows with 2 columns each.
                        Assert.Equal(4, logger.LastCommitResponse?.CommitStats?.MutationCount);
                    }
                }
            });
        }
示例#12
0
        public async Task TestChunking()
        {
            Logger.DefaultLogger.Info(() => $"Seed={_seed}");
            var rowsRead    = 0;
            int rowsToWrite = _random.Next(1, 6);

            using (var connection = _fixture.GetConnection())
            {
                await connection.OpenAsync();

                await RetryHelpers.RetryOnceAsync(async() =>
                {
                    using (var tx = await connection.BeginTransactionAsync())
                    {
                        using (var cmd = connection.CreateInsertCommand(
                                   _fixture.TableName, new SpannerParameterCollection
                        {
                            new SpannerParameter("K", SpannerDbType.String),
                            new SpannerParameter("StringValue", SpannerDbType.String),
                            new SpannerParameter("StringArrayValue", SpannerDbType.ArrayOf(SpannerDbType.String)),
                            new SpannerParameter("BytesValue", SpannerDbType.Bytes),
                            new SpannerParameter("BytesArrayValue", SpannerDbType.ArrayOf(SpannerDbType.Bytes))
                        }))
                        {
                            cmd.Transaction = tx;

                            //write 1-5 rows
                            for (var i = 0; i < rowsToWrite; i++)
                            {
                                await InsertRowAsync(cmd);
                            }

                            await tx.CommitAsync();
                        }
                    }
                });

                using (var readCmd = connection.CreateSelectCommand($"SELECT * FROM {_fixture.TableName}"))
                {
                    using (var reader = await readCmd.ExecuteReaderAsync())
                    {
                        var keySet = new HashSet <string>();
                        while (await reader.ReadAsync())
                        {
                            var k = reader.GetFieldValue <string>("K");
                            if (!_addedKeys.Contains(k))
                            {
                                continue; // this key is from a previous test run.
                            }
                            rowsRead++;
                            Assert.True(keySet.Add(k));
                            Assert.Equal(_stringValues[k], reader.GetFieldValue <string>("StringValue"));
                            Assert.Equal(_stringArrayValues[k], reader.GetFieldValue <string[]>("StringArrayValue"));
                            Assert.Equal(_bytesValues[k], reader.GetFieldValue <byte[]>("BytesValue"));
                            Assert.Equal(_bytesArrayValues[k], reader.GetFieldValue <byte[][]>("BytesArrayValue"));
                        }
                    }
                }
            }

            Assert.Equal(rowsToWrite, rowsRead);
        }