An alternative to UBB.threads
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

293 lines
9.7 KiB

// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as published by
// the Free Software Foundation
//
// There are special exceptions to the terms and conditions of the GPL
// as it is applied to this software. View the full text of the
// exception in file EXCEPTIONS in the directory of this software
// distribution.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Data;
using System.IO;
using System.Threading;
using NUnit.Framework;
using System.Globalization;
namespace MySql.Data.MySqlClient.Tests
{
[TestFixture]
public class TimeoutAndCancel : BaseTest
{
private delegate void CommandInvokerDelegate(MySqlCommand cmdToRun);
private void CommandRunner(MySqlCommand cmdToRun)
{
object o = cmdToRun.ExecuteScalar();
Assert.IsNull(o);
}
[Test]
public void CancelSingleQuery()
{
if (Version < new Version(5, 0)) return;
// first we need a routine that will run for a bit
execSQL(@"CREATE PROCEDURE spTest(duration INT)
BEGIN
SELECT SLEEP(duration);
END");
MySqlCommand cmd = new MySqlCommand("spTest", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("duration", 10);
// now we start execution of the command
CommandInvokerDelegate d = new CommandInvokerDelegate(CommandRunner);
d.BeginInvoke(cmd, null, null);
// sleep 1 seconds
Thread.Sleep(1000);
// now cancel the command
cmd.Cancel();
}
int stateChangeCount;
[Test]
public void WaitTimeoutExpiring()
{
string connStr = GetConnectionString(true);
MySqlConnectionStringBuilder sb = new MySqlConnectionStringBuilder(connStr);
if (sb.ConnectionProtocol == MySqlConnectionProtocol.NamedPipe)
// wait timeout does not work for named pipe connections
return;
using (MySqlConnection c = new MySqlConnection(connStr))
{
c.Open();
c.StateChange += new StateChangeEventHandler(c_StateChange);
// set the session wait timeout on this new connection
MySqlCommand cmd = new MySqlCommand("SET SESSION interactive_timeout=3", c);
cmd.ExecuteNonQuery();
cmd.CommandText = "SET SESSION wait_timeout=2";
cmd.ExecuteNonQuery();
stateChangeCount = 0;
// now wait 4 seconds
Thread.Sleep(4000);
try
{
cmd.CommandText = "SELECT now()";
cmd.ExecuteScalar();
}
catch (Exception ex)
{
Assert.IsTrue(ex.Message.StartsWith("Fatal"));
}
Assert.AreEqual(1, stateChangeCount);
Assert.AreEqual(ConnectionState.Closed, c.State);
}
using (MySqlConnection c = new MySqlConnection(connStr))
{
c.Open();
MySqlCommand cmd = new MySqlCommand("SELECT now() as thetime, database() as db", c);
using (MySqlDataReader r = cmd.ExecuteReader())
{
Assert.IsTrue(r.Read());
}
}
}
void c_StateChange(object sender, StateChangeEventArgs e)
{
stateChangeCount++;
}
[Test]
public void TimeoutExpiring()
{
if (version < new Version(5, 0)) return;
DateTime start = DateTime.Now;
try
{
MySqlCommand cmd = new MySqlCommand("SELECT SLEEP(200)", conn);
cmd.CommandTimeout = 1;
cmd.ExecuteReader(CommandBehavior.SingleRow);
Assert.Fail("Should not get to this point");
}
catch (MySqlException ex)
{
TimeSpan ts = DateTime.Now.Subtract(start);
Assert.IsTrue(ts.TotalSeconds <= 2);
Assert.IsTrue(ex.Message.StartsWith("Timeout expired"), "Message is wrong " +ex.Message);
}
long x = (long)(new MySqlCommand("select 10", conn).ExecuteScalar());
Assert.AreEqual(10, x);
}
[Test]
public void TimeoutNotExpiring()
{
if (Version < new Version(5, 0)) return;
MySqlCommand cmd = new MySqlCommand("SELECT SLEEP(1)", conn);
cmd.CommandTimeout = 2;
cmd.ExecuteNonQuery();
}
[Test]
public void TimeoutDuringBatch()
{
if (Version < new Version(5, 0)) return;
execSQL(@"CREATE PROCEDURE spTest(duration INT)
BEGIN
SELECT SLEEP(duration);
END");
execSQL("CREATE TABLE test (id INT)");
MySqlCommand cmd = new MySqlCommand(
"call spTest(5);INSERT INTO test VALUES(4)", conn);
cmd.CommandTimeout = 2;
try
{
cmd.ExecuteNonQuery();
Assert.Fail("This should have timed out");
}
catch (MySqlException ex)
{
Assert.IsTrue(ex.Message.StartsWith("Timeout expired"), "Message is wrong" +ex);
}
// Check that connection is still usable
MySqlCommand cmd2 = new MySqlCommand("select 10", conn);
long res = (long)cmd2.ExecuteScalar();
Assert.AreEqual(10, res);
}
//[Test]
public void CancelSelect()
{
if (Version < new Version(5, 0)) return;
execSQL("CREATE TABLE Test (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(20))");
for (int i=0; i < 10000; i++)
execSQL("INSERT INTO Test VALUES (NULL, 'my string')");
MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", conn);
cmd.CommandTimeout = 0;
int rows = 0;
using (MySqlDataReader reader = cmd.ExecuteReader())
{
reader.Read();
cmd.Cancel();
while (reader.Read())
{
rows++;
}
}
Assert.IsTrue(rows < 10000);
}
/// <summary>
/// Bug #40091 mysql driver 5.2.3.0 connection pooling issue
/// </summary>
[Test]
public void ConnectionStringModifiedAfterCancel()
{
if (Version.Major < 5) return;
string connStr = GetPoolingConnectionString();
MySqlConnectionStringBuilder sb = new MySqlConnectionStringBuilder(connStr);
if (sb.ConnectionProtocol == MySqlConnectionProtocol.NamedPipe)
// idle named pipe connections cannot be KILLed (server bug#47571)
return;
connStr = connStr.Replace("persist security info=true", "persist security info=false");
int threadId;
using (MySqlConnection c = new MySqlConnection(connStr))
{
c.Open();
threadId = c.ServerThread;
string connStr1 = c.ConnectionString;
MySqlCommand cmd = new MySqlCommand("SELECT SLEEP(2)", c);
cmd.CommandTimeout = 1;
try
{
using (MySqlDataReader reader = cmd.ExecuteReader())
{
}
}
catch (MySqlException ex)
{
Assert.IsTrue(ex.InnerException is TimeoutException);
Assert.IsTrue(c.State == ConnectionState.Open);
}
string connStr2 = c.ConnectionString.ToLower(CultureInfo.InvariantCulture);
Assert.AreEqual(connStr1.ToLower(CultureInfo.InvariantCulture), connStr2);
}
execSQL("kill " + threadId);
}
}
#region Configs
public class TimeoutAndCancelSocketCompressed : TimeoutAndCancel
{
protected override string GetConnectionInfo()
{
return String.Format("port={0};compress=true", port);
}
}
#if !CF
[Category("Pipe")]
public class TimeoutAndCancelPipe : TimeoutAndCancel
{
protected override string GetConnectionInfo()
{
return String.Format("protocol=namedpipe;pipe name={0}", pipeName);
}
}
[Category("SharedMemory")]
public class TimeoutAndCancelSharedMemory : TimeoutAndCancel
{
protected override string GetConnectionInfo()
{
return String.Format("protocol=sharedmemory; shared memory name={0}",
memoryName);
}
}
#endif
#endregion
}