Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ public static void WSHttpBinding_TransactionFlow_Mandatory_RoundTrips()
[WcfFact]
[Condition(nameof(Windows_Authentication_Available), nameof(Skip_CoreWCFService_FailedTest))]
[OuterLoop]
public static void WSHttpBinding_TransactionFlow_Mandatory_WithoutScope_Throws()
public static void WSHttpBinding_TransactionFlow_Mandatory_RoundTrips_And_WithoutScope_Throws()
{
ChannelFactory<IWcfTransactionMandatoryService> factory = null;
IWcfTransactionMandatoryService serviceProxy = null;
Expand All @@ -465,14 +465,28 @@ public static void WSHttpBinding_TransactionFlow_Mandatory_WithoutScope_Throws()
factory = new ChannelFactory<IWcfTransactionMandatoryService>(binding, new EndpointAddress(Endpoints.WSHttpTransactionFlowMandatoryAddress));
serviceProxy = factory.CreateChannel();

// *** EXECUTE & VALIDATE *** \\
// Calling a Mandatory operation without an ambient transaction should throw.
// The client-side TransactionChannel enforces Mandatory by requiring a flowed transaction.
// *** EXECUTE & VALIDATE — negative case (client-side enforcement) *** \\
// Calling a Mandatory operation without an ambient transaction must throw
// before any wire activity. The client-side TransactionChannel enforces
// [TransactionFlow(Mandatory)] by requiring a flowed transaction.
Assert.ThrowsAny<ProtocolException>(() =>
{
serviceProxy.IsTransactionFlowed();
});

// *** EXECUTE & VALIDATE — positive case (true end-to-end) *** \\
// With an ambient transaction, the call must succeed AND the server must
// see the flowed transaction. This portion requires real server support
// for TransactionFlow and exercises the Mandatory contract attribute on
// the wire.
bool flowed;
using (var scope = new TransactionScope(TransactionScopeOption.Required, TransactionScopeAsyncFlowOption.Enabled))
{
flowed = serviceProxy.IsTransactionFlowed();
scope.Complete();
}
Assert.True(flowed, "Expected the transaction to flow to the Mandatory service operation, but IsTransactionFlowed returned false.");

// *** CLEANUP *** \\
factory.Close();
((ICommunicationObject)serviceProxy).Close();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ public static void DefaultSettings_Echo_Cookie()
}

[WcfFact]
// Flaky under CoreWCF on certain Linux distros (Fedora.41, Debian.12):
// the second POST over a keep-alive connection sometimes triggers a
// Kestrel pipe-writer race on the server side
// (System.InvalidOperationException: Writing is not allowed after writer
// was completed -> Connection reset by peer at the client).
[Condition(nameof(Skip_CoreWCFService_FailedTest))]
[OuterLoop]
public static void DefaultSettings_SetCookieOnServerSide()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -356,8 +356,7 @@ public static void WebSocket_Https_Duplex_Streamed(NetHttpMessageEncoding messag
[InlineData(NetHttpMessageEncoding.Binary)]
[InlineData(NetHttpMessageEncoding.Text)]
[InlineData(NetHttpMessageEncoding.Mtom)]
[Condition(nameof(Root_Certificate_Installed),
nameof(Skip_CoreWCFService_FailedTest))]
[Condition(nameof(Root_Certificate_Installed))]
[Issue(3572, OS = OSID.OSX)]
[Issue(1438, OS = OSID.Windows_7)] // not supported on Win7
[OuterLoop]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public static void Certificate_With_CanonicalName_Localhost_Address_EchoString()

[WcfFact]
[Issue(3572, OS = OSID.OSX)]
[Condition(nameof(Root_Certificate_Installed), nameof(Skip_CoreWCFService_FailedTest))]
[Condition(nameof(Root_Certificate_Installed))]
[OuterLoop]
public static void Certificate_With_CanonicalName_DomainName_Address_EchoString()
{
Expand Down Expand Up @@ -175,7 +175,7 @@ public static void Certificate_With_CanonicalName_DomainName_Address_EchoString(

[WcfFact]
[Issue(3572, OS = OSID.OSX)]
[Condition(nameof(Root_Certificate_Installed), nameof(Skip_CoreWCFService_FailedTest))]
[Condition(nameof(Root_Certificate_Installed))]
[OuterLoop]
public static void Certificate_With_CanonicalName_Fqdn_Address_EchoString()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,48 @@ public class CertificateGeneratorLibrary

private static string s_fqdn = Dns.GetHostEntry("127.0.0.1").HostName;
private static string s_hostname = Dns.GetHostEntry("127.0.0.1").HostName.Split('.')[0];

// The SubjectCanonicalName{DomainName,Fqdn} certificates are used by tests that assert a
// NEGATIVE identity check: a client connecting to "localhost" must be rejected because the
// server certificate's CN is a different name. On Windows, Dns.GetHostEntry("127.0.0.1")
// returns the machine name, which satisfies this. On Linux/macOS it returns "localhost",
// making those certs indistinguishable from the localhost cert and breaking the tests.
// Resolve a non-localhost canonical name from the machine name on non-Windows platforms.
// These values are used ONLY for the canonical-name certs; the CRL URI and all other certs
// continue to use s_fqdn/s_hostname so localhost-based CRL fetch and TLS keep working.
private static string s_canonicalFqdn = GetCanonicalFqdn();
private static string s_canonicalHostname = s_canonicalFqdn.Split('.')[0];

private static string s_testserverbase = string.Empty;
private static string s_crlFileLocation = string.Empty;
private static TimeSpan s_validatePeriod;

private static string GetCanonicalFqdn()
{
if (CertificateHelper.CurrentOperatingSystem.IsWindows())
{
return Dns.GetHostEntry("127.0.0.1").HostName;
}

// On Linux/macOS, "127.0.0.1" resolves to "localhost"; use the machine name instead so
// that the canonical-name certificates carry a name distinct from "localhost".
try
{
string resolved = Dns.GetHostEntry(Environment.MachineName).HostName;
if (!string.IsNullOrEmpty(resolved) &&
!string.Equals(resolved, "localhost", StringComparison.OrdinalIgnoreCase))
{
return resolved;
}
}
catch
{
// Name may not be resolvable in some sandboxes; fall back to the raw machine name below.
}

return Environment.MachineName;
}

private static void RemoveCertificatesFromStore(StoreName storeName, StoreLocation storeLocation)
{
X509Store store = CertificateHelper.GetX509Store(storeName, storeLocation);
Expand Down Expand Up @@ -104,7 +142,7 @@ public static int SetupCerts(string testserverbase, TimeSpan validatePeriod, str
certificateCreationSettings = new CertificateCreationSettings()
{
FriendlyName = "WCF Bridge - TcpCertificateWithSubjectCanonicalNameDomainNameResource",
Subject = s_hostname,
Subject = s_canonicalHostname,
SubjectAlternativeNames = new string[0],
ValidityType = CertificateValidityType.NonAuthoritativeForMachine
};
Expand All @@ -114,7 +152,7 @@ public static int SetupCerts(string testserverbase, TimeSpan validatePeriod, str
certificateCreationSettings = new CertificateCreationSettings()
{
FriendlyName = "WCF Bridge - TcpCertificateWithSubjectCanonicalNameFqdnResource",
Subject = s_fqdn,
Subject = s_canonicalFqdn,
SubjectAlternativeNames = new string[0],
ValidityType = CertificateValidityType.NonAuthoritativeForMachine
};
Expand Down