Skip to content

Commit 8d4a9a4

Browse files
committed
enhance integration tests to be able to cover all kinds of key types easily (#2)
Also refactored `KeyStoreBuilder` in order to be able to easily migrate the other key types with the next commits. *Note*: Due to a test first approach commits the comment out line (see TODO) covering all key type to be supported. Signed-off-by: Andreas Schmid <[email protected]>
1 parent a838ef9 commit 8d4a9a4

File tree

6 files changed

+62
-32
lines changed

6 files changed

+62
-32
lines changed

src/main/java/de/aaschmid/taskwarrior/client/KeyStoreBuilder.java

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.io.File;
55
import java.io.FileInputStream;
66
import java.io.IOException;
7+
import java.nio.file.Files;
78
import java.security.KeyFactory;
89
import java.security.KeyStore;
910
import java.security.KeyStore.PasswordProtection;
@@ -16,6 +17,7 @@
1617
import java.security.cert.CertificateException;
1718
import java.security.cert.CertificateFactory;
1819
import java.security.spec.InvalidKeySpecException;
20+
import java.security.spec.KeySpec;
1921
import java.security.spec.PKCS8EncodedKeySpec;
2022
import java.util.ArrayList;
2123
import java.util.List;
@@ -125,21 +127,22 @@ private List<Certificate> createCertificatesFor(File certFile) {
125127
}
126128

127129
private PrivateKey createPrivateKeyFor(File privateKeyFile) {
128-
byte[] privateKeyBytes;
129-
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(privateKeyFile))) {
130-
privateKeyBytes = new byte[(int) privateKeyFile.length()];
131-
int readBytes = bis.read(privateKeyBytes);
132-
if (readBytes != privateKeyFile.length()) {
133-
throw new TaskwarriorKeyStoreException("Failure reading content of '%s': expected %d but received %d bytes.",
134-
privateKeyFile, privateKeyBytes.length, readBytes);
135-
}
130+
try {
131+
byte[] bytes = Files.readAllBytes(privateKeyFile.toPath());
132+
return createPrivateKeyFromPkcs8Der(bytes);
136133
} catch (IOException e) {
137134
throw new TaskwarriorKeyStoreException(e, "Could not read private key of '%s' via input stream.", privateKeyFile);
138135
}
136+
}
137+
138+
private PrivateKey createPrivateKeyFromPkcs8Der(byte[] privateKeyBytes) {
139+
return createPrivateKey(privateKeyFile, new PKCS8EncodedKeySpec(privateKeyBytes));
140+
}
139141

142+
private PrivateKey createPrivateKey(File privateKeyFile, KeySpec keySpec) {
140143
try {
141144
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_PRIVATE_KEY);
142-
return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKeyBytes));
145+
return keyFactory.generatePrivate(keySpec);
143146
} catch (NoSuchAlgorithmException e) {
144147
throw new TaskwarriorKeyStoreException(e, "Key factory could not be initialized for algorithm '%s'.", ALGORITHM_PRIVATE_KEY);
145148
} catch (InvalidKeySpecException e) {

src/main/java/de/aaschmid/taskwarrior/config/TaskwarriorPropertiesConfiguration.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,8 @@
1818
import static de.aaschmid.taskwarrior.config.TaskwarriorPropertiesConfiguration.PropertyKey.USER;
1919
import static java.util.Objects.requireNonNull;
2020

21-
/**
22-
* {@link TaskwarriorConfiguration} based on a specified properties file
23-
*/
24-
class TaskwarriorPropertiesConfiguration implements TaskwarriorConfiguration {
21+
/** {@link TaskwarriorConfiguration} based on a specified properties file */
22+
public class TaskwarriorPropertiesConfiguration implements TaskwarriorConfiguration {
2523

2624
enum PropertyKey {
2725
AUTH_KEY("taskwarrior.auth.key"),
Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,47 @@
11
package de.aaschmid.taskwarrior;
22

3-
import java.net.URL;
3+
import java.util.stream.Stream;
44

55
import de.aaschmid.taskwarrior.client.TaskwarriorClient;
66
import de.aaschmid.taskwarrior.config.TaskwarriorConfiguration;
77
import de.aaschmid.taskwarrior.message.TaskwarriorMessage;
88
import de.aaschmid.taskwarrior.message.TaskwarriorRequestHeader;
99
import de.aaschmid.taskwarrior.test.IntegrationTest;
1010
import org.junit.jupiter.api.Test;
11+
import org.junit.jupiter.params.ParameterizedTest;
12+
import org.junit.jupiter.params.provider.Arguments;
13+
import org.junit.jupiter.params.provider.MethodSource;
1114

12-
import static de.aaschmid.taskwarrior.config.TaskwarriorConfiguration.taskwarriorPropertiesConfiguration;
1315
import static de.aaschmid.taskwarrior.message.TaskwarriorMessage.taskwarriorMessage;
1416
import static de.aaschmid.taskwarrior.message.TaskwarriorRequestHeader.taskwarriorRequestHeaderBuilder;
17+
import static java.lang.String.format;
1518
import static org.assertj.core.api.Assertions.assertThat;
1619
import static org.assertj.core.api.Assertions.entry;
1720

1821
@IntegrationTest
1922
class TaskwarriorClientIntegrationTest {
2023

21-
private static final URL PROPERTIES_TASKWARRIOR =
22-
TaskwarriorClientIntegrationTest.class.getResource("/integTest.taskwarrior.properties");
23-
private static final TaskwarriorConfiguration CONFIG = taskwarriorPropertiesConfiguration(PROPERTIES_TASKWARRIOR);
24-
2524
private static final String SYNC_KEY = "f92d5c8d-4cf9-4cf5-b72f-1f4a70cf9b20";
2625

27-
private final TaskwarriorClient client = new TaskwarriorClient(CONFIG);
26+
static Stream<Arguments> configs() {
27+
return Stream.of("pkcs8-der")
28+
// return Stream.of("pkcs1", "pkcs8", "pkcs8-der") // TODO use to test all key type to be supported
29+
.map(keyType -> format("/taskwarrior.%s.properties", keyType))
30+
.map(TaskwarriorClientIntegrationTest.class::getResource)
31+
.map(TaskwarriorConfiguration::taskwarriorPropertiesConfiguration)
32+
.map(Arguments::of);
33+
}
2834

29-
@Test
30-
void statistics() {
35+
@ParameterizedTest
36+
@MethodSource("configs")
37+
void statistics(TaskwarriorConfiguration config) {
3138
TaskwarriorRequestHeader header = taskwarriorRequestHeaderBuilder()
32-
.authentication(CONFIG)
39+
.authentication(config)
3340
.type(TaskwarriorRequestHeader.MessageType.STATISTICS)
3441
.build();
3542
TaskwarriorMessage message = taskwarriorMessage(header.toMap());
3643

37-
TaskwarriorMessage response = client.sendAndReceive(message);
44+
TaskwarriorMessage response = clientFor(config).sendAndReceive(message);
3845

3946
assertThat(response.getHeaders())
4047
.contains(entry("code", "200"))
@@ -45,15 +52,16 @@ void statistics() {
4552
assertThat(response.getPayload()).isNotPresent();
4653
}
4754

48-
@Test
49-
void syncWithoutSyncKey() {
55+
@ParameterizedTest
56+
@MethodSource("configs")
57+
void syncWithoutSyncKey(TaskwarriorConfiguration config) {
5058
TaskwarriorRequestHeader header = taskwarriorRequestHeaderBuilder()
51-
.authentication(CONFIG)
59+
.authentication(config)
5260
.type(TaskwarriorRequestHeader.MessageType.SYNC)
5361
.build();
5462
TaskwarriorMessage message = taskwarriorMessage(header.toMap());
5563

56-
TaskwarriorMessage response = client.sendAndReceive(message);
64+
TaskwarriorMessage response = clientFor(config).sendAndReceive(message);
5765

5866
assertThat(response.getHeaders())
5967
.contains(entry("code", "200"))
@@ -63,19 +71,24 @@ void syncWithoutSyncKey() {
6371
.endsWith(SYNC_KEY));
6472
}
6573

66-
@Test
67-
void syncWithSyncKey() {
74+
@ParameterizedTest
75+
@MethodSource("configs")
76+
void syncWithSyncKey(TaskwarriorConfiguration config) {
6877
TaskwarriorRequestHeader header = taskwarriorRequestHeaderBuilder()
69-
.authentication(CONFIG)
78+
.authentication(config)
7079
.type(TaskwarriorRequestHeader.MessageType.SYNC)
7180
.build();
7281
TaskwarriorMessage message = taskwarriorMessage(header.toMap(), SYNC_KEY);
7382

74-
TaskwarriorMessage response = client.sendAndReceive(message);
83+
TaskwarriorMessage response = clientFor(config).sendAndReceive(message);
7584

7685
assertThat(response.getHeaders())
7786
.contains(entry("code", "201"))
7887
.contains(entry("status", "No change"));
7988
assertThat(response.getPayload()).hasValue(SYNC_KEY);
8089
}
90+
91+
private TaskwarriorClient clientFor(TaskwarriorConfiguration config) {
92+
return new TaskwarriorClient(config);
93+
}
8194
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
taskwarrior.server.host=localhost
2+
taskwarrior.server.port=53589
3+
taskwarrior.ssl.cert.ca.file=docker/taskd/pki/ca.cert.pem
4+
taskwarrior.ssl.cert.key.file=docker/taskd/pki/client.cert.pem
5+
taskwarrior.ssl.private.key.file=docker/taskd/pki/client.key.pem
6+
taskwarrior.auth.organization=Public
7+
taskwarrior.auth.user=Task Warrior
8+
taskwarrior.auth.key=921c0dd2-728e-4a44-8605-68262754dd99
File renamed without changes.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
taskwarrior.server.host=localhost
2+
taskwarrior.server.port=53589
3+
taskwarrior.ssl.cert.ca.file=docker/taskd/pki/ca.cert.pem
4+
taskwarrior.ssl.cert.key.file=docker/taskd/pki/client.cert.pem
5+
taskwarrior.ssl.private.key.file=docker/taskd/pki/client.pkcs8.key.pem
6+
taskwarrior.auth.organization=Public
7+
taskwarrior.auth.user=Task Warrior
8+
taskwarrior.auth.key=921c0dd2-728e-4a44-8605-68262754dd99

0 commit comments

Comments
 (0)