* chore: Read test certs from resources folder

This will avoid importing bouncy castle library just for tests

Signed-off-by: Javier Aliaga <javier@diagrid.io>

* ci: Split unit test and integration tests

Signed-off-by: Javier Aliaga <javier@diagrid.io>

---------

Signed-off-by: Javier Aliaga <javier@diagrid.io>
This commit is contained in:
Javier Aliaga 2025-08-29 09:56:06 +02:00 committed by GitHub
parent 6b0b79d04c
commit e25f52a13a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 305 additions and 295 deletions

View File

@ -15,6 +15,35 @@ on:
- release-*
jobs:
test:
name: "Unit tests"
runs-on: ubuntu-latest
timeout-minutes: 30
continue-on-error: false
env:
JDK_VER: 17
steps:
- uses: actions/checkout@v5
- name: Set up OpenJDK ${{ env.JDK_VER }}
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: ${{ env.JDK_VER }}
- name: Run tests
run: ./mvnw clean install -B -q
- name: Codecov
uses: codecov/codecov-action@v5.5.0
- name: Upload test report for sdk
uses: actions/upload-artifact@v4
with:
name: test-dapr-java-sdk-jdk${{ env.JDK_VER }}
path: sdk/target/jacoco-report/
- name: Upload test report for sdk-actors
uses: actions/upload-artifact@v4
with:
name: report-dapr-java-sdk-actors-jdk${{ env.JDK_VER }}
path: sdk-actors/target/jacoco-report/
build:
name: "Build jdk:${{ matrix.java }} sb:${{ matrix.spring-boot-display-version }} exp:${{ matrix.experimental }}"
runs-on: ubuntu-latest
@ -114,27 +143,11 @@ jobs:
/home/runner/.local/bin/toxiproxy-server --version
- name: Clean up and install sdk
run: ./mvnw clean install -B -q -DskipTests
- name: Unit tests
run: ./mvnw test # making it temporarily verbose.
env:
DOCKER_HOST: ${{steps.setup_docker.outputs.sock}}
- name: Codecov
uses: codecov/codecov-action@v5.5.0
- name: Integration tests using spring boot version ${{ matrix.spring-boot-version }}
id: integration_tests
run: PRODUCT_SPRING_BOOT_VERSION=${{ matrix.spring-boot-version }} ./mvnw -B -Pintegration-tests verify
env:
DOCKER_HOST: ${{steps.setup_docker.outputs.sock}}
- name: Upload test report for sdk
uses: actions/upload-artifact@v4
with:
name: report-dapr-java-sdk-jdk${{ matrix.java }}-sb${{ matrix.spring-boot-version }}
path: sdk/target/jacoco-report/
- name: Upload test report for sdk-actors
uses: actions/upload-artifact@v4
with:
name: report-dapr-java-sdk-actors-jdk${{ matrix.java }}-sb${{ matrix.spring-boot-version }}
path: sdk-actors/target/jacoco-report/
- name: Upload failsafe test report for sdk-tests on failure
if: ${{ failure() && steps.integration_tests.conclusion == 'failure' }}
uses: actions/upload-artifact@v4
@ -150,7 +163,7 @@ jobs:
publish:
runs-on: ubuntu-latest
needs: build
needs: [ build, test ]
timeout-minutes: 30
env:
JDK_VER: 17

View File

@ -132,18 +132,6 @@
<artifactId>assertj-core</artifactId>
<version>${assertj.version}</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.70</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.70</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>

View File

@ -27,20 +27,9 @@ import org.junit.jupiter.api.condition.EnabledOnOs;
import org.junit.jupiter.api.condition.OS;
import java.io.File;
import java.nio.file.Files;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.ArrayList;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
public class NetworkUtilsTest {
private final int defaultGrpcPort = 50001;
@ -48,47 +37,6 @@ public class NetworkUtilsTest {
private ManagedChannel channel;
private static final List<ManagedChannel> channels = new ArrayList<>();
// Helper method to generate a self-signed certificate for testing
private static KeyPair generateKeyPair() throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
return keyPairGenerator.generateKeyPair();
}
private static X509Certificate generateCertificate(KeyPair keyPair) throws Exception {
X500Name issuer = new X500Name("CN=Test Certificate");
X500Name subject = new X500Name("CN=Test Certificate");
Date notBefore = new Date(System.currentTimeMillis() - 24 * 60 * 60 * 1000);
Date notAfter = new Date(System.currentTimeMillis() + 365 * 24 * 60 * 60 * 1000L);
SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded());
X509v3CertificateBuilder certBuilder = new X509v3CertificateBuilder(
issuer,
java.math.BigInteger.valueOf(System.currentTimeMillis()),
notBefore,
notAfter,
subject,
publicKeyInfo
);
ContentSigner signer = new JcaContentSignerBuilder("SHA256withRSA").build(keyPair.getPrivate());
X509Certificate cert = new JcaX509CertificateConverter().getCertificate(certBuilder.build(signer));
return cert;
}
private static void writeCertificateToFile(X509Certificate cert, File file) throws Exception {
String certPem = "-----BEGIN CERTIFICATE-----\n" +
java.util.Base64.getEncoder().encodeToString(cert.getEncoded()) +
"\n-----END CERTIFICATE-----";
Files.write(file.toPath(), certPem.getBytes());
}
private static void writePrivateKeyToFile(KeyPair keyPair, File file) throws Exception {
String keyPem = "-----BEGIN PRIVATE KEY-----\n" +
java.util.Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded()) +
"\n-----END PRIVATE KEY-----";
Files.write(file.toPath(), keyPem.getBytes());
}
@AfterEach
public void tearDown() {
if (channel != null && !channel.isShutdown()) {
@ -157,56 +105,35 @@ public class NetworkUtilsTest {
@Test
public void testBuildGrpcManagedChannelWithTls() throws Exception {
// Generate test certificate and key
KeyPair keyPair = generateKeyPair();
X509Certificate cert = generateCertificate(keyPair);
File certFile = File.createTempFile("test-cert", ".pem");
File keyFile = File.createTempFile("test-key", ".pem");
try {
writeCertificateToFile(cert, certFile);
writePrivateKeyToFile(keyPair, keyFile);
File certFile = new File(this.getClass().getResource("/certs/test-cert.pem").getFile());
File keyFile = new File(this.getClass().getResource("/certs/test-cert.key").getFile());
var properties = new Properties(Map.of(
var properties = new Properties(Map.of(
Properties.GRPC_TLS_CERT_PATH.getName(), certFile.getAbsolutePath(),
Properties.GRPC_TLS_KEY_PATH.getName(), keyFile.getAbsolutePath()
));
channel = NetworkUtils.buildGrpcManagedChannel(properties);
channels.add(channel);
String expectedAuthority = String.format("%s:%s", defaultSidecarIP, defaultGrpcPort);
Assertions.assertEquals(expectedAuthority, channel.authority());
} finally {
certFile.delete();
keyFile.delete();
}
channel = NetworkUtils.buildGrpcManagedChannel(properties);
channels.add(channel);
String expectedAuthority = String.format("%s:%s", defaultSidecarIP, defaultGrpcPort);
Assertions.assertEquals(expectedAuthority, channel.authority());
}
@Test
public void testBuildGrpcManagedChannelWithTlsAndEndpoint() throws Exception {
// Generate test certificate and key
KeyPair keyPair = generateKeyPair();
X509Certificate cert = generateCertificate(keyPair);
File certFile = File.createTempFile("test-cert", ".pem");
File keyFile = File.createTempFile("test-key", ".pem");
try {
writeCertificateToFile(cert, certFile);
writePrivateKeyToFile(keyPair, keyFile);
File certFile = new File(this.getClass().getResource("/certs/test-cert.pem").getFile());
File keyFile = new File(this.getClass().getResource("/certs/test-cert.key").getFile());
var properties = new Properties(Map.of(
Properties.GRPC_TLS_CERT_PATH.getName(), certFile.getAbsolutePath(),
Properties.GRPC_TLS_KEY_PATH.getName(), keyFile.getAbsolutePath(),
Properties.GRPC_ENDPOINT.getName(), "https://example.com:443"
));
var properties = new Properties(Map.of(
Properties.GRPC_TLS_CERT_PATH.getName(), certFile.getAbsolutePath(),
Properties.GRPC_TLS_KEY_PATH.getName(), keyFile.getAbsolutePath(),
Properties.GRPC_ENDPOINT.getName(), "https://example.com:443"
));
channel = NetworkUtils.buildGrpcManagedChannel(properties);
channels.add(channel);
Assertions.assertEquals("example.com:443", channel.authority());
} finally {
certFile.delete();
keyFile.delete();
}
channel = NetworkUtils.buildGrpcManagedChannel(properties);
channels.add(channel);
Assertions.assertEquals("example.com:443", channel.authority());
}
@Test
@ -229,49 +156,32 @@ public class NetworkUtilsTest {
System.getProperty("os.name").toLowerCase().contains("mac"));
// Generate test certificate and key
KeyPair keyPair = generateKeyPair();
X509Certificate cert = generateCertificate(keyPair);
File certFile = File.createTempFile("test-cert", ".pem");
File keyFile = File.createTempFile("test-key", ".pem");
File certFile = new File(this.getClass().getResource("/certs/test-cert.pem").getFile());
File keyFile = new File(this.getClass().getResource("/certs/test-cert.key").getFile());
var properties = new Properties(Map.of(
Properties.GRPC_TLS_CERT_PATH.getName(), certFile.getAbsolutePath(),
Properties.GRPC_TLS_KEY_PATH.getName(), keyFile.getAbsolutePath(),
Properties.GRPC_ENDPOINT.getName(), "unix:/tmp/test.sock"
));
// For Unix sockets, we expect an exception if the platform doesn't support it
try {
writeCertificateToFile(cert, certFile);
writePrivateKeyToFile(keyPair, keyFile);
var properties = new Properties(Map.of(
Properties.GRPC_TLS_CERT_PATH.getName(), certFile.getAbsolutePath(),
Properties.GRPC_TLS_KEY_PATH.getName(), keyFile.getAbsolutePath(),
Properties.GRPC_ENDPOINT.getName(), "unix:/tmp/test.sock"
));
// For Unix sockets, we expect an exception if the platform doesn't support it
try {
channel = NetworkUtils.buildGrpcManagedChannel(properties);
channels.add(channel);
// If we get here, Unix sockets are supported
Assertions.assertNotNull(channel.authority(), "Channel authority should not be null");
} catch (Exception e) {
// If we get here, Unix sockets are not supported
Assertions.assertTrue(e.getMessage().contains("DomainSocketAddress"));
}
} finally {
certFile.delete();
keyFile.delete();
channel = NetworkUtils.buildGrpcManagedChannel(properties);
channels.add(channel);
// If we get here, Unix sockets are supported
Assertions.assertNotNull(channel.authority(), "Channel authority should not be null");
} catch (Exception e) {
// If we get here, Unix sockets are not supported
Assertions.assertTrue(e.getMessage().contains("DomainSocketAddress"));
}
}
@Test
public void testBuildGrpcManagedChannelWithTlsAndDnsAuthority() throws Exception {
// Generate test certificate and key
KeyPair keyPair = generateKeyPair();
X509Certificate cert = generateCertificate(keyPair);
File certFile = File.createTempFile("test-cert", ".pem");
File keyFile = File.createTempFile("test-key", ".pem");
try {
writeCertificateToFile(cert, certFile);
writePrivateKeyToFile(keyPair, keyFile);
File certFile = new File(this.getClass().getResource("/certs/test-cert.pem").getFile());
File keyFile = new File(this.getClass().getResource("/certs/test-cert.key").getFile());
var properties = new Properties(Map.of(
Properties.GRPC_TLS_CERT_PATH.getName(), certFile.getAbsolutePath(),
Properties.GRPC_TLS_KEY_PATH.getName(), keyFile.getAbsolutePath(),
@ -281,44 +191,26 @@ public class NetworkUtilsTest {
channel = NetworkUtils.buildGrpcManagedChannel(properties);
channels.add(channel);
Assertions.assertEquals("example.com:443", channel.authority());
} finally {
certFile.delete();
keyFile.delete();
}
}
@Test
public void testBuildGrpcManagedChannelWithTlsAndCaCert() throws Exception {
// Generate test CA certificate
KeyPair caKeyPair = generateKeyPair();
X509Certificate caCert = generateCertificate(caKeyPair);
File caCertFile = File.createTempFile("test-ca-cert", ".pem");
try {
writeCertificateToFile(caCert, caCertFile);
File caCertFile = new File(this.getClass().getResource("/certs/test-ca-cert.pem").getFile());
var properties = new Properties(Map.of(
Properties.GRPC_TLS_CA_PATH.getName(), caCertFile.getAbsolutePath()
));
var properties = new Properties(Map.of(
Properties.GRPC_TLS_CA_PATH.getName(), caCertFile.getAbsolutePath()
));
channel = NetworkUtils.buildGrpcManagedChannel(properties);
channels.add(channel);
String expectedAuthority = String.format("%s:%s", defaultSidecarIP, defaultGrpcPort);
Assertions.assertEquals(expectedAuthority, channel.authority());
} finally {
caCertFile.delete();
}
channel = NetworkUtils.buildGrpcManagedChannel(properties);
channels.add(channel);
String expectedAuthority = String.format("%s:%s", defaultSidecarIP, defaultGrpcPort);
Assertions.assertEquals(expectedAuthority, channel.authority());
}
@Test
public void testBuildGrpcManagedChannelWithTlsAndCaCertAndEndpoint() throws Exception {
// Generate test CA certificate
KeyPair caKeyPair = generateKeyPair();
X509Certificate caCert = generateCertificate(caKeyPair);
File caCertFile = File.createTempFile("test-ca-cert", ".pem");
try {
writeCertificateToFile(caCert, caCertFile);
File caCertFile = new File(this.getClass().getResource("/certs/test-ca-cert.pem").getFile());
var properties = new Properties(Map.of(
Properties.GRPC_TLS_CA_PATH.getName(), caCertFile.getAbsolutePath(),
@ -328,9 +220,7 @@ public class NetworkUtilsTest {
channel = NetworkUtils.buildGrpcManagedChannel(properties);
channels.add(channel);
Assertions.assertEquals("example.com:443", channel.authority());
} finally {
caCertFile.delete();
}
}
@Test
@ -346,37 +236,22 @@ public class NetworkUtilsTest {
@Test
public void testBuildGrpcManagedChannelWithMtlsAndCaCert() throws Exception {
// Generate test certificates
KeyPair caKeyPair = generateKeyPair();
X509Certificate caCert = generateCertificate(caKeyPair);
KeyPair clientKeyPair = generateKeyPair();
X509Certificate clientCert = generateCertificate(clientKeyPair);
File caCertFile = File.createTempFile("test-ca-cert", ".pem");
File clientCertFile = File.createTempFile("test-client-cert", ".pem");
File clientKeyFile = File.createTempFile("test-client-key", ".pem");
try {
writeCertificateToFile(caCert, caCertFile);
writeCertificateToFile(clientCert, clientCertFile);
writePrivateKeyToFile(clientKeyPair, clientKeyFile);
File caCertFile = new File(this.getClass().getResource("/certs/test-ca-cert.pem").getFile());
File clientCertFile = new File(this.getClass().getResource("/certs/test-cert.pem").getFile());
File clientKeyFile = new File(this.getClass().getResource("/certs/test-cert.key").getFile());
// Test mTLS with both client certs and CA cert
var properties = new Properties(Map.of(
Properties.GRPC_TLS_CA_PATH.getName(), caCertFile.getAbsolutePath(),
Properties.GRPC_TLS_CERT_PATH.getName(), clientCertFile.getAbsolutePath(),
Properties.GRPC_TLS_KEY_PATH.getName(), clientKeyFile.getAbsolutePath()
));
// Test mTLS with both client certs and CA cert
var properties = new Properties(Map.of(
Properties.GRPC_TLS_CA_PATH.getName(), caCertFile.getAbsolutePath(),
Properties.GRPC_TLS_CERT_PATH.getName(), clientCertFile.getAbsolutePath(),
Properties.GRPC_TLS_KEY_PATH.getName(), clientKeyFile.getAbsolutePath()
));
channel = NetworkUtils.buildGrpcManagedChannel(properties);
channels.add(channel);
String expectedAuthority = String.format("%s:%s", defaultSidecarIP, defaultGrpcPort);
Assertions.assertEquals(expectedAuthority, channel.authority());
Assertions.assertFalse(channel.isTerminated(), "Channel should be active");
} finally {
caCertFile.delete();
clientCertFile.delete();
clientKeyFile.delete();
}
channel = NetworkUtils.buildGrpcManagedChannel(properties);
channels.add(channel);
String expectedAuthority = String.format("%s:%s", defaultSidecarIP, defaultGrpcPort);
Assertions.assertEquals(expectedAuthority, channel.authority());
Assertions.assertFalse(channel.isTerminated(), "Channel should be active");
}
@Test
@ -463,57 +338,40 @@ public class NetworkUtilsTest {
@Test
public void testBuildGrpcManagedChannelWithCaCertAndUnixSocket() throws Exception {
// Skip test if Unix domain sockets are not supported
Assumptions.assumeTrue(System.getProperty("os.name").toLowerCase().contains("linux") ||
System.getProperty("os.name").toLowerCase().contains("mac"));
Assumptions.assumeTrue(System.getProperty("os.name").toLowerCase().contains("linux") ||
System.getProperty("os.name").toLowerCase().contains("mac"));
// Generate test CA certificate
KeyPair caKeyPair = generateKeyPair();
X509Certificate caCert = generateCertificate(caKeyPair);
File caCertFile = File.createTempFile("test-ca-cert", ".pem");
File caCertFile = new File(this.getClass().getResource("/certs/test-ca-cert.pem").getFile());
var properties = new Properties(Map.of(
Properties.GRPC_TLS_CA_PATH.getName(), caCertFile.getAbsolutePath(),
Properties.GRPC_ENDPOINT.getName(), "unix:/tmp/test.sock"
));
// For Unix sockets, we expect an exception if the platform doesn't support it
try {
writeCertificateToFile(caCert, caCertFile);
var properties = new Properties(Map.of(
Properties.GRPC_TLS_CA_PATH.getName(), caCertFile.getAbsolutePath(),
Properties.GRPC_ENDPOINT.getName(), "unix:/tmp/test.sock"
));
// For Unix sockets, we expect an exception if the platform doesn't support it
try {
channel = NetworkUtils.buildGrpcManagedChannel(properties);
channels.add(channel);
Assertions.assertNotNull(channel.authority(), "Channel authority should not be null");
} catch (Exception e) {
// If we get here, Unix sockets are not supported
Assertions.assertTrue(e.getMessage().contains("DomainSocketAddress"));
}
} finally {
caCertFile.delete();
channel = NetworkUtils.buildGrpcManagedChannel(properties);
channels.add(channel);
Assertions.assertNotNull(channel.authority(), "Channel authority should not be null");
} catch (Exception e) {
// If we get here, Unix sockets are not supported
Assertions.assertTrue(e.getMessage().contains("DomainSocketAddress"));
}
}
@Test
public void testBuildGrpcManagedChannelWithCaCertAndDnsAuthority() throws Exception {
// Generate test CA certificate
KeyPair caKeyPair = generateKeyPair();
X509Certificate caCert = generateCertificate(caKeyPair);
File caCertFile = File.createTempFile("test-ca-cert", ".pem");
try {
writeCertificateToFile(caCert, caCertFile);
File caCertFile = new File(this.getClass().getResource("/certs/test-ca-cert.pem").getFile());
var properties = new Properties(Map.of(
Properties.GRPC_TLS_CA_PATH.getName(), caCertFile.getAbsolutePath(),
Properties.GRPC_ENDPOINT.getName(), "dns://authority:53/example.com:443"
));
var properties = new Properties(Map.of(
Properties.GRPC_TLS_CA_PATH.getName(), caCertFile.getAbsolutePath(),
Properties.GRPC_ENDPOINT.getName(), "dns://authority:53/example.com:443"
));
channel = NetworkUtils.buildGrpcManagedChannel(properties);
channels.add(channel);
Assertions.assertEquals("example.com:443", channel.authority());
} finally {
caCertFile.delete();
}
channel = NetworkUtils.buildGrpcManagedChannel(properties);
channels.add(channel);
Assertions.assertEquals("example.com:443", channel.authority());
}
@Test
@ -536,43 +394,28 @@ public class NetworkUtilsTest {
@Test
public void testBuildGrpcManagedChannelWithInsecureTlsAndMtls() throws Exception {
// Generate test certificates
KeyPair caKeyPair = generateKeyPair();
X509Certificate caCert = generateCertificate(caKeyPair);
KeyPair clientKeyPair = generateKeyPair();
X509Certificate clientCert = generateCertificate(clientKeyPair);
File caCertFile = File.createTempFile("test-ca-cert", ".pem");
File clientCertFile = File.createTempFile("test-client-cert", ".pem");
File clientKeyFile = File.createTempFile("test-client-key", ".pem");
try {
writeCertificateToFile(caCert, caCertFile);
writeCertificateToFile(clientCert, clientCertFile);
writePrivateKeyToFile(clientKeyPair, clientKeyFile);
File caCertFile = new File(this.getClass().getResource("/certs/test-ca-cert.pem").getFile());
File clientCertFile = new File(this.getClass().getResource("/certs/test-cert.pem").getFile());
File clientKeyFile = new File(this.getClass().getResource("/certs/test-cert.key").getFile());
// Test that insecure TLS still works with mTLS settings
// The client certs should be ignored since we're using InsecureTrustManagerFactory
var properties = new Properties(Map.of(
Properties.GRPC_TLS_INSECURE.getName(), "true",
Properties.GRPC_TLS_CA_PATH.getName(), caCertFile.getAbsolutePath(),
Properties.GRPC_TLS_CERT_PATH.getName(), clientCertFile.getAbsolutePath(),
Properties.GRPC_TLS_KEY_PATH.getName(), clientKeyFile.getAbsolutePath(),
Properties.GRPC_ENDPOINT.getName(), "dns:///example.com:443?tls=true"
));
// Test that insecure TLS still works with mTLS settings
// The client certs should be ignored since we're using InsecureTrustManagerFactory
var properties = new Properties(Map.of(
Properties.GRPC_TLS_INSECURE.getName(), "true",
Properties.GRPC_TLS_CA_PATH.getName(), caCertFile.getAbsolutePath(),
Properties.GRPC_TLS_CERT_PATH.getName(), clientCertFile.getAbsolutePath(),
Properties.GRPC_TLS_KEY_PATH.getName(), clientKeyFile.getAbsolutePath(),
Properties.GRPC_ENDPOINT.getName(), "dns:///example.com:443?tls=true"
));
channel = NetworkUtils.buildGrpcManagedChannel(properties);
channels.add(channel);
// Verify the channel is created with the correct authority
Assertions.assertEquals("example.com:443", channel.authority());
// Verify the channel is active and using TLS (not plaintext)
Assertions.assertFalse(channel.isTerminated(), "Channel should be active");
} finally {
caCertFile.delete();
clientCertFile.delete();
clientKeyFile.delete();
}
channel = NetworkUtils.buildGrpcManagedChannel(properties);
channels.add(channel);
// Verify the channel is created with the correct authority
Assertions.assertEquals("example.com:443", channel.authority());
// Verify the channel is active and using TLS (not plaintext)
Assertions.assertFalse(channel.isTerminated(), "Channel should be active");
}
@Test

View File

@ -0,0 +1,52 @@
-----BEGIN PRIVATE KEY-----
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
fg8QEv831uJb0uItcjDy5Yr0TEYMqg==
-----END PRIVATE KEY-----

View File

@ -0,0 +1,31 @@
-----BEGIN CERTIFICATE-----
MIIFUzCCAzugAwIBAgIUFHmlZNi1305lvonC4ePOulB207UwDQYJKoZIhvcNAQEL
BQAwOTENMAsGA1UECgwEREFQUjENMAsGA1UECwwEREFQUjEZMBcGA1UEAwwQVEVT
VCBDRVJUSUZJQ0FURTAeFw0yNTA4MjgxNTI4MTlaFw0yNzA4MjgxNTI4MTlaMDkx
DTALBgNVBAoMBERBUFIxDTALBgNVBAsMBERBUFIxGTAXBgNVBAMMEFRFU1QgQ0VS
VElGSUNBVEUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDbzg+ow2pe
+tWKSISVIF6kFi9VYReq0sJ8gJ+mQRkBK7Hs8G0WD9KS+Ebg15CTEulNbyp3sqPa
28tD1bq69ST8aMjUxD8NyWyYd7NQSd7pWHuR+NMDsh908W+JDyTxGgonXFaU5s8m
+FAS25nC8dzEgolxrQlVraXld1ZxMVW/OnOdl4dlSsXpGR4Zwv2S4BrppQvGhGTK
aURuOI1mot0IZVnV4acg5iK+2wPvDD2UJp6fMR6PplKrgb8dV2SqEEEVPwsXY0nb
idRb3yJ6VRtibkbu7u987BpEEaNeSmsC0BOIeHj90Jc+ilDQEgVRkMvP9zSPh6yY
4kOuMevof2J86FTRZWo7b9u1BG/2WoLeOPk00kAzN2jmk4hnytknWz1G0dxVZSJr
OcLHv9tWKk4TI3l54DrKw+n3pQA2Qs22P97n6d151mi3Yr45YtypmQhn4f4tsLxT
16mp2Vs/D4vU1M4jldpi9vDin+R4wIgDxXThUUd3c6NqrhyRiLteRaZVVsWeudi/
jZt7H676S5lVdLTsU1jmOxef1mTzJxNAhw7VClq8YXeq8Z65Mj84fARxEh+WgN31
5+JlIE6gPdYz7A+h5pupDVXJdhOViafQMBsAkUWautz4n47F5X+oB53rKEvRjjgV
sSVNB3oLBWCoXPxfpANQjNXky9QRb2Ib1wIDAQABo1MwUTAdBgNVHQ4EFgQUnBy0
t/3jxb0LK0SWaKjOlRlebmowHwYDVR0jBBgwFoAUnBy0t/3jxb0LK0SWaKjOlRle
bmowDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAh/5qDtYaiTWN
3cX0H/ucdsT1fzVCiWmniRBrvGgLOJ4VfBpcGAeyt3nTOCGBpLIHi6M47mv6+DA8
GVA+k4FgAbFRWgSR5zDsOOC0/jTTEMpcrz13DgpCeh/Jj0MdNe3nzkC+eAT2bp07
ZYLrO++N+IEpDEuDz3YlqIpgKpEREoGKWXrXcCEdsAUbIjOSWBfLBTuF8x11IVi7
V4y3UUVTg6aA8ILmtWStoBuVroOH/HY/8RuQztUejjtd3PIEzPRgITekpWEDxI1D
Ycc7ZgdxEYmzXTvRAmLkIAoSPR5U61i09SSHmCs9hoWUGQGxSsxBFloTH6IoJFls
VDeWw3Shzu1PSPP5NedGgdRC8GKjOVDAgXzYPSoTYab5mGHTbL3HtRELthCmQSaC
SrNwKjd1MmhJ6yrjxKruE9mpSHUu50IDIP+PyMokWMRf504eGvPJstvD6+I4sUS3
/Owu0eGM3incgG/ulAWpRDCXRq49JpAoq7evbyBQyzDfrCSN0U6sgjBVlJuoEuXD
t1cNmvPxf0730HxQYrq1nYahdt5Mi9+Pv8ublylKuGeYiWqiSeSE6wRRTktL7Xmf
BotM8yvJBhpY00GAPSxXQ2Kl+OielJq9QSCOgtQkMCMzKMsfbO+YA+WvMICe+GNJ
sfrgLw0imYT1npKJbNtg/vRxTZFj9hc=
-----END CERTIFICATE-----

View File

@ -0,0 +1,52 @@
-----BEGIN PRIVATE KEY-----
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
mfPgTPwyRZiGKrz43GpgD0Zg/eytPw==
-----END PRIVATE KEY-----

View File

@ -0,0 +1,31 @@
-----BEGIN CERTIFICATE-----
MIIFUzCCAzugAwIBAgIUbPytgC1pfbqeBSbdOok03mPcoU8wDQYJKoZIhvcNAQEL
BQAwOTENMAsGA1UECgwEREFQUjENMAsGA1UECwwEREFQUjEZMBcGA1UEAwwQVGVz
dCBDZXJ0aWZpY2F0ZTAeFw0yNTA4MjgxNTIzMzJaFw0yNzA4MjgxNTIzMzJaMDkx
DTALBgNVBAoMBERBUFIxDTALBgNVBAsMBERBUFIxGTAXBgNVBAMMEFRlc3QgQ2Vy
dGlmaWNhdGUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCX9WC+9qfC
u7LhLTkm1XpYnIFowqlIAARHxWv08xbOIm/4bUtruuy0nOEVzzYiu8fdRP2LsBp9
iKuRJzBw6QOeASeepCorOFnU24bG3oAdjPHp7Bj76tM1GW5H8izOlln22My4asaO
P4kxC+LQt7aolF1Ca7A9J3TNEBxSaowUpCCDtwNnBTPoFa28vhFjga32BnNEZCTP
WCrn97WfDKj4trb+lQIt77jSBpPmwBJIqsOaM02uIlnF8MElX2TEUfMFGWAzDBml
lB80cZHybC2Ic2nrYKuuHtpZrtMM6atGstxiHDt002p6yxUUEbcXE1SvB6ZGuBDw
9frpF7J5xnRQ7PAaKl17hXinnOPG/b3xtvOrx2rewWHHUxfCDzzaDcr1+31zfoW8
3wcwfcuuS8E9iO4mIIYKoB+3C0430IMlqv61BVlHB9FajSEXhg8KIRDB8dZZGX4Y
95teRGv4s69Wr0gFFrPG5XJ0m4gS7mpkJeYwTrvtgb2Rm+D7vjxKR4xW8zSRnj4W
644YSpBI9n/fCw3wmWAvs+2wt1m6JcvXyOFJPY96BQWE3eIGV052OCc69rXUhEV/
vFRVNn4UJMCGptpJZiTM+/jvC94YEY2GzMu0jfuBYrnzeeasRnnVh6gfFKXui3xK
GApmMoqfd/2DogdmMXilZQ4SHinS6Bj0yQIDAQABo1MwUTAdBgNVHQ4EFgQUuj4S
u+I/pBSJFGVoCK4y+QvGm/QwHwYDVR0jBBgwFoAUuj4Su+I/pBSJFGVoCK4y+QvG
m/QwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAR18zFnyf22+h
bLT8ab0fD6pLQUW0/yr0PpsNNrsnNbTMr+tgOQDZgi/jpnG8eQmyA5aVjBxgxBNq
BhXFMixVputyafbb+fCIGvwWAMGtKL3Jf2yYfn6IhMftMB2e3xp4hUNBfRC92fVT
McypKFf/bWPxk7ZDeZGwNK0CViB2XNDCPWvR+RxQI4stilpN47/fAQdpnAmcDVi6
wVljILTaPhgpWj0Q3c6ccdgFE8ETRQK46dDW6C2KstIjqOxP4Go5HQw5bGTQVRPw
bX2v7kadLfFDJJDwmCRUNzQJfWM+8qROy8YgexFe5rBUkOOFCz2Wd2I0LjiN8SrP
aY3iEoZQO/bIUPJsi3qtLgb9HDZ6iXeB1SHEXnn/l0b1zpb2kumdhiNif2s1NXsw
LQV7xai3xrdT96fnWElqD39gHunLO2hCE4ra7YJ3yZnXyi21EdErhpCaD1aPo96d
0m/2rbIfafrBZFdcu4hvS56qtnVajOfXaN5bCKyRsByA8Ebv2XlWWWCRDii5ft/W
RYrRDZhC6t9dZNv1ObhDLzx/2FNq82lxhi4VCwlAy6Qdc8kY7uh92IWUUQoLonQB
QI0QuROI9W9Vc/DUJFvts/qCKWtD0XdoTVlZc/1B2WFbiwZ5U04x5inFBtudvyEL
ZEyQNL0MVlOgpxK3igY4xKM8r+m4bi4=
-----END CERTIFICATE-----