diff --git a/tests/AVEVA.Historian.Client.Tests/HistorianSessionRoundTripTests.cs b/tests/AVEVA.Historian.Client.Tests/HistorianSessionRoundTripTests.cs
new file mode 100644
index 0000000..1cfce4d
--- /dev/null
+++ b/tests/AVEVA.Historian.Client.Tests/HistorianSessionRoundTripTests.cs
@@ -0,0 +1,88 @@
+using AVEVA.Historian.Client.Models;
+using Xunit.Abstractions;
+
+namespace AVEVA.Historian.Client.Tests;
+
+///
+/// Live end-to-end round-trip for : open → write → read → status →
+/// ping → dispose — ALL on ONE reused session (no re-handshake). Env-gated exactly like
+/// (silent skip without HISTORIAN_GRPC_HOST +
+/// HISTORIAN_WRITE_SANDBOX_TAG + HISTORIAN_USER). Bounded write to the sandbox tag only.
+///
+public sealed class HistorianSessionRoundTripTests
+{
+ private readonly ITestOutputHelper _output;
+
+ public HistorianSessionRoundTripTests(ITestOutputHelper output) => _output = output;
+
+ [Fact]
+ public async Task Session_WriteReadStatusPing_AllOnOneSession()
+ {
+ string? host = Environment.GetEnvironmentVariable("HISTORIAN_GRPC_HOST");
+ string? sandboxTag = Environment.GetEnvironmentVariable("HISTORIAN_WRITE_SANDBOX_TAG");
+ if (string.IsNullOrWhiteSpace(host) || string.IsNullOrWhiteSpace(sandboxTag)
+ || string.IsNullOrEmpty(Environment.GetEnvironmentVariable("HISTORIAN_USER")))
+ {
+ return; // skip — env not configured
+ }
+
+ HistorianClientOptions options = BuildOptions(host);
+ await using var client = new HistorianClient(options);
+ await using HistorianSession session = await client.OpenSessionAsync(HistorianSessionKind.WriteEnabled, CancellationToken.None);
+
+ // 1) write on the session
+ bool wrote = await session.AddHistoricalValuesAsync(sandboxTag,
+ new[] { new HistorianHistoricalValue(DateTime.UtcNow, 42.0, OpcQuality: 192) },
+ CancellationToken.None);
+ Assert.True(wrote);
+ _output.WriteLine("1) write -> ok");
+
+ // 2) read on the SAME session
+ DateTime end = DateTime.UtcNow, start = end - TimeSpan.FromDays(7);
+ var rows = new List();
+ await foreach (HistorianSample s in session.ReadRawAsync(sandboxTag, start, end, 8, CancellationToken.None))
+ rows.Add(s);
+ _output.WriteLine($"2) session read rows={rows.Count}");
+ Assert.NotEmpty(rows);
+
+ // 3) status + ping on the SAME session
+ string? version = await session.GetSystemParameterAsync("HistorianVersion", CancellationToken.None);
+ Assert.False(string.IsNullOrWhiteSpace(version));
+ _output.WriteLine($"3) HistorianVersion={version}");
+
+ await session.PingAsync(CancellationToken.None); // must not throw
+ _output.WriteLine("4) ping -> ok");
+
+ _output.WriteLine("session round-trip OK (write+read+status+ping on one session)");
+ }
+
+ // verbatim copy of BuildOptions from HandshakeReuseSpikeTests
+ private static HistorianClientOptions BuildOptions(string host)
+ {
+ string? user = Environment.GetEnvironmentVariable("HISTORIAN_USER");
+ string? password = Environment.GetEnvironmentVariable("HISTORIAN_PASSWORD");
+ bool explicitCreds = !string.IsNullOrEmpty(user);
+ int port = int.TryParse(Environment.GetEnvironmentVariable("HISTORIAN_GRPC_PORT"), out int parsed)
+ ? parsed
+ : HistorianClientOptions.DefaultGrpcPort;
+ bool tls = string.Equals(Environment.GetEnvironmentVariable("HISTORIAN_GRPC_TLS"), "true", StringComparison.OrdinalIgnoreCase);
+ TimeSpan timeout = int.TryParse(Environment.GetEnvironmentVariable("HISTORIAN_GRPC_TIMEOUT"), out int secs) && secs > 0
+ ? TimeSpan.FromSeconds(secs)
+ : new HistorianClientOptions { Host = host }.RequestTimeout;
+
+ return new HistorianClientOptions
+ {
+ Host = host,
+ Port = port,
+ Transport = HistorianTransport.RemoteGrpc,
+ GrpcUseTls = tls,
+ AllowUntrustedServerCertificate = tls,
+ ServerDnsIdentity = Environment.GetEnvironmentVariable("HISTORIAN_GRPC_DNSID"),
+ IntegratedSecurity = !explicitCreds,
+ UserName = user ?? string.Empty,
+ Password = password ?? string.Empty,
+ RequestTimeout = timeout,
+ Compression = true
+ };
+ }
+}