public void BasicLifecycle()
{
using (var conn = new NpgsqlConnection(ConnectionString))
{
bool eventOpen = false, eventClosed = false, eventBroken = false;
conn.StateChange += (s, e) =>
{
if (e.OriginalState == ConnectionState.Closed && e.CurrentState == ConnectionState.Open)
eventOpen = true;
if (e.OriginalState == ConnectionState.Open && e.CurrentState == ConnectionState.Closed)
eventClosed = true;
};
Assert.That(conn.State, Is.EqualTo(ConnectionState.Closed));
Assert.That(conn.FullState, Is.EqualTo(ConnectionState.Closed));
// TODO: Connecting state?
conn.Open();
Assert.That(conn.State, Is.EqualTo(ConnectionState.Open));
Assert.That(conn.FullState, Is.EqualTo(ConnectionState.Open));
Assert.That(conn.Connector.State, Is.EqualTo(ConnectorState.Ready));
Assert.That(eventOpen, Is.True);
using (var cmd = new NpgsqlCommand("SELECT 1", conn))
using (var reader = cmd.ExecuteReader())
{
reader.Read();
Assert.That(conn.FullState, Is.EqualTo(ConnectionState.Open | ConnectionState.Fetching));
Assert.That(conn.State, Is.EqualTo(ConnectionState.Open));
Assert.That(conn.Connector.State, Is.EqualTo(ConnectorState.Fetching));
}
Assert.That(conn.FullState, Is.EqualTo(ConnectionState.Open));
Assert.That(conn.State, Is.EqualTo(ConnectionState.Open));
Assert.That(conn.Connector.State, Is.EqualTo(ConnectorState.Ready));
using (var cmd = CreateSleepCommand(conn, 1))
{
var exitFlag = false;
var pollingTask = Task.Factory.StartNew(() =>
{
while (true)
{
if (exitFlag) {
Assert.Fail("Connection did not reach the Executing state");
}
if (conn.Connector.State == ConnectorState.Executing)
{
Assert.That(conn.FullState & ConnectionState.Executing, Is.Not.EqualTo(0));
Assert.That(conn.State, Is.EqualTo(ConnectionState.Open));
return;
}
}
});
cmd.ExecuteNonQuery();
exitFlag = true;
pollingTask.Wait();
}
conn.Close();
Assert.That(conn.State, Is.EqualTo(ConnectionState.Closed));
Assert.That(conn.FullState, Is.EqualTo(ConnectionState.Closed));
Assert.That(eventClosed, Is.True);
conn.Open();
Assert.That(conn.State, Is.EqualTo(ConnectionState.Open));
Assert.That(conn.FullState, Is.EqualTo(ConnectionState.Open));
Assert.That(conn.Connector.State, Is.EqualTo(ConnectorState.Ready));
using (var conn2 = OpenConnection())
conn2.ExecuteNonQuery($"SELECT pg_terminate_backend({conn.ProcessID})");
conn.StateChange += (sender, args) =>
{
if (args.CurrentState == ConnectionState.Closed)
eventBroken = true;
};
// Allow some time for the pg_terminate to kill our connection
using (var cmd = CreateSleepCommand(conn, 10))
Assert.That(() => cmd.ExecuteNonQuery(), Throws.Exception
.TypeOf<NpgsqlException>()
.With.InnerException.InstanceOf<IOException>()
);
Assert.That(conn.State, Is.EqualTo(ConnectionState.Closed));
Assert.That(conn.FullState, Is.EqualTo(ConnectionState.Broken));
Assert.That(eventBroken, Is.True);
}
}