Fix bugs exposed by testing with Gradle

The following issues are addressed:
- XML sanitizer should preserve input encoding. Gradle loses any that is not UTF-8. Bazel loses any that is not ASCII.
- Verify that XML sanitizer works with non-UTF8 encoding
- GpgSystemCommandRule breaks when $TMPDIR env variable is not set
- TestDataHelper throws exception when loading resources if resources are plain files on default file system as opposed to being in a jar file.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=216537258
This commit is contained in:
weiminyu 2018-10-10 08:51:27 -07:00 committed by Ben McIlwain
parent 218c4517eb
commit 9e02502fd4
4 changed files with 84 additions and 24 deletions

View file

@ -17,6 +17,7 @@ package google.registry.flows;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.flows.EppXmlSanitizer.sanitizeEppXml;
import static google.registry.testing.TestDataHelper.loadBytes;
import static java.nio.charset.StandardCharsets.UTF_16LE;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.collect.ImmutableMap;
@ -30,12 +31,12 @@ import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class EppXmlSanitizerTest {
private static final String XML_HEADER = "<?xml version=\"1.0\" ?>";
private static final String UTF8_HEADER = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
@Test
public void testSanitize_noSensitiveData_noop() throws Exception {
byte[] inputXmlBytes = loadBytes(getClass(), "host_create.xml").read();
String expectedXml = XML_HEADER + new String(inputXmlBytes, UTF_8);
String expectedXml = UTF8_HEADER + new String(inputXmlBytes, UTF_8);
String sanitizedXml = sanitizeEppXml(inputXmlBytes);
assertThat(sanitizedXml).isEqualTo(expectedXml);
@ -50,7 +51,7 @@ public class EppXmlSanitizerTest {
ImmutableMap.of("PW", "oldpass", "NEWPW", "newPw"))
.getEppXml();
String expectedXml =
XML_HEADER
UTF8_HEADER
+ new EppLoader(
this,
"login_update_password.xml",
@ -68,7 +69,7 @@ public class EppXmlSanitizerTest {
this, "login_wrong_case.xml", ImmutableMap.of("PW", "oldpass", "NEWPW", "newPw"))
.getEppXml();
String expectedXml =
XML_HEADER
UTF8_HEADER
+ new EppLoader(
this,
"login_wrong_case.xml",
@ -83,7 +84,7 @@ public class EppXmlSanitizerTest {
public void testSanitize_contactAuthInfo_sanitized() throws Exception {
byte[] inputXmlBytes = loadBytes(getClass(), "contact_info.xml").read();
String expectedXml =
XML_HEADER
UTF8_HEADER
+ new EppLoader(this, "contact_info_sanitized.xml", ImmutableMap.of()).getEppXml();
String sanitizedXml = sanitizeEppXml(inputXmlBytes);
@ -94,7 +95,7 @@ public class EppXmlSanitizerTest {
public void testSanitize_contactCreateResponseAuthInfo_sanitized() throws Exception {
byte[] inputXmlBytes = loadBytes(getClass(), "contact_info_from_create_response.xml").read();
String expectedXml =
XML_HEADER
UTF8_HEADER
+ new EppLoader(
this, "contact_info_from_create_response_sanitized.xml", ImmutableMap.of())
.getEppXml();
@ -106,7 +107,7 @@ public class EppXmlSanitizerTest {
@Test
public void testSanitize_emptyElement_transformedToLongForm() {
byte[] inputXmlBytes = "<pw/>".getBytes(UTF_8);
assertThat(sanitizeEppXml(inputXmlBytes)).isEqualTo(XML_HEADER + "<pw></pw>\n");
assertThat(sanitizeEppXml(inputXmlBytes)).isEqualTo(UTF8_HEADER + "<pw></pw>\n");
}
@Test
@ -119,7 +120,22 @@ public class EppXmlSanitizerTest {
@Test
public void testSanitize_unicode_hasCorrectCharCount() {
byte[] inputXmlBytes = "<pw>\u007F\u4E43x</pw>".getBytes(UTF_8);
String expectedXml = XML_HEADER + "<pw>C**</pw>\n";
String expectedXml = UTF8_HEADER + "<pw>C**</pw>\n";
assertThat(sanitizeEppXml(inputXmlBytes)).isEqualTo(expectedXml);
}
@Test
public void testSanitize_emptyString_encodedToBase64() {
byte[] inputXmlBytes = "".getBytes(UTF_8);
assertThat(sanitizeEppXml(inputXmlBytes)).isEqualTo("");
}
@Test
public void testSanitize_utf16_encodingPreserved() {
// Test data should specify an endian-specific UTF-16 scheme for easy assertion. If 'UTF-16' is
// used, the XMLEventReader in sanitizer may resolve it to an endian-specific one.
String inputXml = "<?xml version=\"1.0\" encoding=\"UTF-16LE\"?><p>\u03bc</p>\n";
String sanitizedXml = sanitizeEppXml(inputXml.getBytes(UTF_16LE));
assertThat(sanitizedXml).isEqualTo(inputXml);
}
}

View file

@ -17,6 +17,7 @@ package google.registry.testing;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Strings.isNullOrEmpty;
import static com.google.common.truth.Truth.assertWithMessage;
import static java.nio.charset.StandardCharsets.UTF_8;
@ -84,9 +85,14 @@ public final class GpgSystemCommandRule extends ExternalResource {
@Override
protected void before() throws IOException, InterruptedException {
checkState(Objects.equals(cwd, DEV_NULL));
File tmpRoot = null;
tmpRoot = new File(System.getenv("TMPDIR"));
cwd = File.createTempFile(TEMP_FILE_PREFIX, "", tmpRoot);
String tmpRootDirString = System.getenv("TMPDIR");
// Create the working directory for the forked process on Temp file system. Create under the
// path specified by 'TMPDIR' envrionment variable if defined, otherwise create under the
// runtime's default (typically /tmp).
cwd =
isNullOrEmpty(tmpRootDirString)
? File.createTempFile(TEMP_FILE_PREFIX, "")
: File.createTempFile(TEMP_FILE_PREFIX, "", new File(tmpRootDirString));
cwd.delete();
cwd.mkdir();
conf = new File(cwd, ".gnupg");
@ -118,6 +124,7 @@ public final class GpgSystemCommandRule extends ExternalResource {
@Override
protected void after() {
// TODO(weiminyu): we should delete the cwd tree.
cwd = DEV_NULL;
conf = DEV_NULL;
}

View file

@ -23,7 +23,9 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.io.ByteSource;
import com.google.common.io.MoreFiles;
import com.google.common.io.Resources;
import java.io.IOException;
import java.net.URI;
import java.nio.file.FileSystemAlreadyExistsException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
@ -93,7 +95,21 @@ public final class TestDataHelper {
/** Returns a recursive iterable of all files in the given directory. */
public static Iterable<Path> listFiles(Class<?> context, String directory) throws Exception {
URI dir = Resources.getResource(context, directory).toURI();
FileSystems.newFileSystem(dir, ImmutableMap.of("create", "true"));
ensureFileSystemPresentForUri(dir);
return MoreFiles.fileTraverser().breadthFirst(Paths.get(dir));
}
private static void ensureFileSystemPresentForUri(URI uri) throws IOException {
if (uri.getScheme().equals(FileSystems.getDefault().provider().getScheme())) {
// URI maps to default file system (file://...), which must be present. Besides, calling
// FileSystem.newFileSystem on this URI may trigger FileSystemAlreadyExistsException.
return;
}
try {
// URI maps to a special file system, e.g., jar:...
FileSystems.newFileSystem(uri, ImmutableMap.of("create", "true"));
} catch (FileSystemAlreadyExistsException e) {
// ignore.
}
}
}