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
293 lines
9.7 KiB
15 years ago
|
// 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
|
||
|
|
||
|
}
|