Simplify the RyDE API

Second step of RDE encoding refactoring.

Creates a single OutputStream encode RyDE files.
This replaces the 5 OutputStreams that were needed before.

Also removes all the factories that were injected. It's an encoding, there's no point in injecting it.

Finally, removed the buffer-size configuration and replaced with a static final
const value in each individual OutputStream.

This doesn't yet include a decoder (InputStream). And there's still a lot of overlap between the Ryde and the Ghostryde code. Both of those are left for the next CLs.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=204898369
This commit is contained in:
guyben 2018-07-17 05:50:04 -07:00 committed by jianglai
parent c4a2b5fa8d
commit 8ec2eaf39c
15 changed files with 215 additions and 345 deletions

View file

@ -100,11 +100,6 @@ public class BrdaCopyActionTest extends ShardableTestCase {
@Before
public void before() throws Exception {
action.gcsUtils = gcsUtils;
action.pgpCompressionFactory = new RydePgpCompressionOutputStreamFactory(() -> 1024);
action.pgpEncryptionFactory = new RydePgpEncryptionOutputStreamFactory(() -> 1024);
action.pgpFileFactory = new RydePgpFileOutputStreamFactory(() -> 1024);
action.pgpSigningFactory = new RydePgpSigningOutputStreamFactory();
action.tarFactory = new RydeTarOutputStreamFactory();
action.tld = "lol";
action.watermark = DateTime.parse("2010-10-17TZ");
action.brdaBucket = "tub";

View file

@ -70,7 +70,6 @@ import google.registry.testing.FakeKeyringModule;
import google.registry.testing.FakeResponse;
import google.registry.testing.FakeSleeper;
import google.registry.testing.GpgSystemCommandRule;
import google.registry.testing.IoSpyRule;
import google.registry.testing.Lazies;
import google.registry.testing.TaskQueueHelper.TaskMatcher;
import google.registry.testing.sftp.SftpServerRule;
@ -81,10 +80,8 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.URI;
import org.bouncycastle.openpgp.PGPKeyPair;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.joda.time.DateTime;
import org.junit.Before;
@ -131,11 +128,6 @@ public class RdeUploadActionTest {
RdeTestData.loadBytes("pgp-public-keyring.asc"),
RdeTestData.loadBytes("pgp-private-keyring-escrow.asc"));
@Rule
public final IoSpyRule ioSpy = new IoSpyRule()
.checkClosedOnlyOnce()
.checkCharIoMaxCalls(10);
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
@ -146,42 +138,6 @@ public class RdeUploadActionTest {
private final EscrowTaskRunner runner = mock(EscrowTaskRunner.class);
private final FakeClock clock = new FakeClock(DateTime.parse("2010-10-17TZ"));
private final RydeTarOutputStreamFactory tarFactory =
new RydeTarOutputStreamFactory() {
@Override
public RydeTarOutputStream create(
OutputStream os, long size, DateTime modified, String filename) {
return ioSpy.register(super.create(os, size, modified, filename));
}};
private final RydePgpFileOutputStreamFactory literalFactory =
new RydePgpFileOutputStreamFactory(() -> BUFFER_SIZE) {
@Override
public RydePgpFileOutputStream create(OutputStream os, DateTime modified, String filename) {
return ioSpy.register(super.create(os, modified, filename));
}};
private final RydePgpEncryptionOutputStreamFactory encryptFactory =
new RydePgpEncryptionOutputStreamFactory(() -> BUFFER_SIZE) {
@Override
public RydePgpEncryptionOutputStream create(OutputStream os, PGPPublicKey publicKey) {
return ioSpy.register(super.create(os, publicKey));
}};
private final RydePgpCompressionOutputStreamFactory compressFactory =
new RydePgpCompressionOutputStreamFactory(() -> BUFFER_SIZE) {
@Override
public RydePgpCompressionOutputStream create(OutputStream os) {
return ioSpy.register(super.create(os));
}};
private final RydePgpSigningOutputStreamFactory signFactory =
new RydePgpSigningOutputStreamFactory() {
@Override
public RydePgpSigningOutputStream create(OutputStream os, PGPKeyPair signingKey) {
return ioSpy.register(super.create(os, signingKey));
}};
private RdeUploadAction createAction(URI uploadUrl) {
try (Keyring keyring = new FakeKeyringModule().get()) {
RdeUploadAction action = new RdeUploadAction();
@ -195,11 +151,6 @@ public class RdeUploadActionTest {
keyring.getRdeSshClientPublicKey());
action.jschSshSessionFactory = new JSchSshSessionFactory(standardSeconds(3));
action.response = response;
action.pgpCompressionFactory = compressFactory;
action.pgpEncryptionFactory = encryptFactory;
action.pgpFileFactory = literalFactory;
action.pgpSigningFactory = signFactory;
action.tarFactory = tarFactory;
action.bucket = "bucket";
action.interval = standardDays(1);
action.timeout = standardSeconds(23);

View file

@ -68,12 +68,6 @@ public class RydeGpgIntegrationTest extends ShardableTestCase {
new GpgCommand("gpg2"),
};
@DataPoints
public static BufferSize[] bufferSizes = new BufferSize[] {
new BufferSize(1),
new BufferSize(7),
};
@DataPoints
public static Filename[] filenames = new Filename[] {
new Filename("sloth"),
@ -88,22 +82,11 @@ public class RydeGpgIntegrationTest extends ShardableTestCase {
};
@Theory
public void test(GpgCommand cmd, BufferSize bufSize, Filename name, Content content)
public void test(GpgCommand cmd, Filename name, Content content)
throws Exception {
assumeTrue(hasCommand("tar"));
assumeTrue(hasCommand(cmd.get() + " --version"));
RydeTarOutputStreamFactory tarFactory =
new RydeTarOutputStreamFactory();
RydePgpFileOutputStreamFactory pgpFileFactory =
new RydePgpFileOutputStreamFactory(bufSize::get);
RydePgpEncryptionOutputStreamFactory pgpEncryptionFactory =
new RydePgpEncryptionOutputStreamFactory(bufSize::get);
RydePgpCompressionOutputStreamFactory pgpCompressionFactory =
new RydePgpCompressionOutputStreamFactory(bufSize::get);
RydePgpSigningOutputStreamFactory pgpSigningFactory =
new RydePgpSigningOutputStreamFactory();
Keyring keyring = keyringFactory.get();
PGPKeyPair signingKey = keyring.getRdeSigningKey();
PGPPublicKey receiverKey = keyring.getRdeReceiverKey();
@ -116,20 +99,13 @@ public class RydeGpgIntegrationTest extends ShardableTestCase {
byte[] data = content.get().getBytes(UTF_8);
try (OutputStream rydeOut = new FileOutputStream(rydeFile);
RydePgpSigningOutputStream signLayer = pgpSigningFactory.create(rydeOut, signingKey)) {
try (RydePgpEncryptionOutputStream encryptLayer =
pgpEncryptionFactory.create(signLayer, receiverKey);
RydePgpCompressionOutputStream compressLayer =
pgpCompressionFactory.create(encryptLayer);
RydePgpFileOutputStream fileLayer =
pgpFileFactory.create(compressLayer, modified, name.get() + ".tar");
RydeTarOutputStream tarLayer =
tarFactory.create(fileLayer, data.length, modified, name.get() + ".xml")) {
tarLayer.write(data);
}
try (OutputStream sigOut = new FileOutputStream(sigFile)) {
sigOut.write(signLayer.getSignature());
}
OutputStream sigOut = new FileOutputStream(sigFile);
RydeEncoder rydeEncoder = new RydeEncoder.Builder()
.setRydeOutput(rydeOut, receiverKey)
.setSignatureOutput(sigOut, signingKey)
.setFileMetadata(name.get(), data.length, modified)
.build()) {
rydeEncoder.write(data);
}
// Iron Mountain examines the ryde file to see what sort of OpenPGP layers it contains.
@ -252,18 +228,6 @@ public class RydeGpgIntegrationTest extends ShardableTestCase {
}
}
private static class BufferSize {
private final int value;
BufferSize(int value) {
this.value = value;
}
int get() {
return value;
}
}
private static class Filename {
private final String value;

View file

@ -1,121 +0,0 @@
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.testing;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.atMost;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.CheckReturnValue;
import org.junit.rules.ExternalResource;
/** JUnit Rule that uses Mockito to spy on I/O streams to make sure they're healthy. */
public final class IoSpyRule extends ExternalResource {
private boolean checkClosedOnlyOnce;
private boolean checkClosedAtLeastOnce;
private int checkCharIoMaxCalls = -1;
private final List<Closeable> spiedCloseables = new ArrayList<>();
private final List<InputStream> spiedInputStreams = new ArrayList<>();
private final List<OutputStream> spiedOutputStreams = new ArrayList<>();
public IoSpyRule() {}
/**
* Enables check where {@link Closeable#close() close} must be called EXACTLY once.
*
* <p>This is sort of pedantic, since Java's contract for close specifies that it must permit
* multiple calls.
*/
public IoSpyRule checkClosedOnlyOnce() {
checkState(!checkClosedAtLeastOnce, "you're already using checkClosedAtLeastOnce()");
checkClosedOnlyOnce = true;
return this;
}
/** Enables check where {@link Closeable#close() close} must be called at least once. */
public IoSpyRule checkClosedAtLeastOnce() {
checkState(!checkClosedOnlyOnce, "you're already using checkClosedOnlyOnce()");
checkClosedAtLeastOnce = true;
return this;
}
/** Enables check to make sure your streams aren't going too slow with char-based I/O. */
public IoSpyRule checkCharIoMaxCalls(int value) {
checkArgument(value >= 0, "value >= 0");
checkCharIoMaxCalls = value;
return this;
}
/** Adds your {@link Closeable} to the list of streams to check, and returns its mocked self. */
@CheckReturnValue
public <T extends Closeable> T register(T stream) {
T res = spy(stream);
spiedCloseables.add(res);
if (stream instanceof InputStream) {
spiedInputStreams.add((InputStream) res);
}
if (stream instanceof OutputStream) {
spiedOutputStreams.add((OutputStream) res);
}
return res;
}
@Override
protected void after() {
checkState(checkClosedOnlyOnce
|| checkClosedAtLeastOnce
|| checkCharIoMaxCalls != -1,
"At least one check must be enabled.");
try {
check();
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
spiedCloseables.clear();
spiedInputStreams.clear();
spiedOutputStreams.clear();
}
}
private void check() throws IOException {
for (Closeable stream : spiedCloseables) {
if (checkClosedAtLeastOnce) {
verify(stream, atLeastOnce()).close();
} else if (checkClosedOnlyOnce) {
verify(stream, times(1)).close();
}
}
if (checkCharIoMaxCalls != -1) {
for (InputStream stream : spiedInputStreams) {
verify(stream, atMost(checkCharIoMaxCalls)).read();
}
for (OutputStream stream : spiedOutputStreams) {
verify(stream, atMost(checkCharIoMaxCalls)).write(anyInt());
}
}
}
}

View file

@ -20,11 +20,6 @@ import static google.registry.testing.TestDataHelper.loadBytes;
import com.google.common.io.ByteSource;
import com.google.common.io.Files;
import google.registry.rde.RdeTestData;
import google.registry.rde.RydePgpCompressionOutputStreamFactory;
import google.registry.rde.RydePgpEncryptionOutputStreamFactory;
import google.registry.rde.RydePgpFileOutputStreamFactory;
import google.registry.rde.RydePgpSigningOutputStreamFactory;
import google.registry.rde.RydeTarOutputStreamFactory;
import google.registry.testing.BouncyCastleProviderRule;
import google.registry.testing.FakeKeyringModule;
import java.io.File;
@ -43,11 +38,6 @@ public class EncryptEscrowDepositCommandTest
static EscrowDepositEncryptor createEncryptor() {
EscrowDepositEncryptor res = new EscrowDepositEncryptor();
res.pgpCompressionFactory = new RydePgpCompressionOutputStreamFactory(() -> 1024);
res.pgpEncryptionFactory = new RydePgpEncryptionOutputStreamFactory(() -> 1024);
res.pgpFileFactory = new RydePgpFileOutputStreamFactory(() -> 1024);
res.pgpSigningFactory = new RydePgpSigningOutputStreamFactory();
res.tarFactory = new RydeTarOutputStreamFactory();
res.rdeReceiverKey = () -> new FakeKeyringModule().get().getRdeReceiverKey();
res.rdeSigningKey = () -> new FakeKeyringModule().get().getRdeSigningKey();
return res;