1dae61a374
Reviewed-by: rriggs, lancea
202 lines
7.7 KiB
Java
202 lines
7.7 KiB
Java
/*
|
|
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
|
|
|
import java.io.ByteArrayInputStream;
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.IOException;
|
|
import java.util.jar.Attributes;
|
|
import java.util.jar.Manifest;
|
|
import java.util.jar.Attributes.Name;
|
|
import java.lang.reflect.Field;
|
|
|
|
import org.testng.annotations.Test;
|
|
import static org.testng.Assert.*;
|
|
|
|
/**
|
|
* @test
|
|
* @bug 8066619
|
|
* @modules java.base/java.util.jar:+open
|
|
* @run testng/othervm NullAndEmptyKeysAndValues
|
|
* @summary Tests manifests with {@code null} and empty string {@code ""}
|
|
* values as section name, header name, or value in both main and named
|
|
* attributes sections.
|
|
*/
|
|
/*
|
|
* Note to future maintainer:
|
|
* In order to actually being able to test all the cases where key and values
|
|
* are null normal manifest and attributes manipulation through their public
|
|
* api is not sufficient but then there were these null checks there before
|
|
* which may or may not have had their reason and this way it's ensured that
|
|
* the behavior does not change with that respect.
|
|
* Once module isolation is enforced some test cases will not any longer be
|
|
* possible and those now tested situations will be guaranteed not to occur
|
|
* any longer at all at which point the corresponding tests can be removed
|
|
* safely without replacement unless of course another way is found inject the
|
|
* tested null values.
|
|
* Another trick to access package private class members could be to use
|
|
* deserialization or adding a new class to the same package on the classpath.
|
|
* Here is not important how the values are set to null because it shows that
|
|
* the behavior remains unchanged.
|
|
*/
|
|
public class NullAndEmptyKeysAndValues {
|
|
|
|
static final String SOME_KEY = "some-key";
|
|
static final String SOME_VALUE = "some value";
|
|
static final String NULL_TEXT = "null";
|
|
static final String EMPTY_STR = "";
|
|
static final Name EMPTY_NAME = new Name("tmp") {{
|
|
try {
|
|
Field name = Name.class.getDeclaredField("name");
|
|
name.setAccessible(true);
|
|
name.set(this, EMPTY_STR);
|
|
} catch (Exception e) {
|
|
throw new RuntimeException(e.getMessage(), e);
|
|
}
|
|
}};
|
|
|
|
@Test
|
|
public void testMainAttributesHeaderNameNull() throws Exception {
|
|
Manifest mf = new Manifest();
|
|
Field attr = mf.getClass().getDeclaredField("attr");
|
|
attr.setAccessible(true);
|
|
Attributes mainAtts = new Attributes() {{
|
|
super.put(null, SOME_VALUE);
|
|
}};
|
|
attr.set(mf, mainAtts);
|
|
mf.getMainAttributes().put(Name.MANIFEST_VERSION, "1.0");
|
|
assertThrows(NullPointerException.class, () -> writeAndRead(mf));
|
|
}
|
|
|
|
@Test
|
|
public void testMainAttributesHeaderNameEmpty() throws Exception {
|
|
Manifest mf = new Manifest();
|
|
mf.getMainAttributes().put(Name.MANIFEST_VERSION, "1.0");
|
|
mf.getMainAttributes().put(EMPTY_NAME, SOME_VALUE);
|
|
assertThrows(IOException.class, () -> writeAndRead(mf));
|
|
}
|
|
|
|
@Test
|
|
public void testMainAttributesHeaderValueNull() throws Exception {
|
|
Manifest mf = new Manifest();
|
|
Field attr = mf.getClass().getDeclaredField("attr");
|
|
attr.setAccessible(true);
|
|
Attributes mainAtts = new Attributes() {{
|
|
map.put(new Name(SOME_KEY), null);
|
|
}};
|
|
attr.set(mf, mainAtts);
|
|
mf.getMainAttributes().put(Name.MANIFEST_VERSION, "1.0");
|
|
mf = writeAndRead(mf);
|
|
assertEquals(mf.getMainAttributes().getValue(SOME_KEY), NULL_TEXT);
|
|
}
|
|
|
|
@Test
|
|
public void testMainAttributesHeaderValueEmpty() throws Exception {
|
|
Manifest mf = new Manifest();
|
|
Field attr = mf.getClass().getDeclaredField("attr");
|
|
attr.setAccessible(true);
|
|
Attributes mainAtts = new Attributes() {{
|
|
map.put(new Name(SOME_KEY), EMPTY_STR);
|
|
}};
|
|
attr.set(mf, mainAtts);
|
|
mf.getMainAttributes().put(Name.MANIFEST_VERSION, "1.0");
|
|
mf = writeAndRead(mf);
|
|
assertEquals(mf.getMainAttributes().getValue(SOME_KEY), EMPTY_STR);
|
|
}
|
|
|
|
@Test
|
|
public void testSectionNameNull() throws IOException {
|
|
Manifest mf = new Manifest();
|
|
mf.getMainAttributes().put(Name.MANIFEST_VERSION, "1.0");
|
|
mf.getEntries().put(null, new Attributes());
|
|
mf = writeAndRead(mf);
|
|
assertNotNull(mf.getEntries().get(NULL_TEXT));
|
|
}
|
|
|
|
@Test
|
|
public void testSectionNameEmpty() throws IOException {
|
|
Manifest mf = new Manifest();
|
|
mf.getMainAttributes().put(Name.MANIFEST_VERSION, "1.0");
|
|
mf.getEntries().put(EMPTY_STR, new Attributes());
|
|
mf = writeAndRead(mf);
|
|
assertNotNull(mf.getEntries().get(EMPTY_STR));
|
|
}
|
|
|
|
@Test
|
|
public void testNamedSectionHeaderNameNull() throws IOException {
|
|
Manifest mf = new Manifest();
|
|
mf.getMainAttributes().put(Name.MANIFEST_VERSION, "1.0");
|
|
mf.getEntries().put(SOME_KEY, new Attributes() {{
|
|
map.put(null, SOME_VALUE);
|
|
}});
|
|
assertThrows(NullPointerException.class, () -> writeAndRead(mf));
|
|
}
|
|
|
|
@Test
|
|
public void testNamedSectionHeaderNameEmpty() throws IOException {
|
|
Manifest mf = new Manifest();
|
|
mf.getMainAttributes().put(Name.MANIFEST_VERSION, "1.0");
|
|
mf.getEntries().put(SOME_KEY, new Attributes() {{
|
|
map.put(EMPTY_NAME, SOME_VALUE);
|
|
}});
|
|
assertThrows(IOException.class, () -> writeAndRead(mf));
|
|
}
|
|
|
|
@Test
|
|
public void testNamedSectionHeaderValueNull() throws IOException {
|
|
Manifest mf = new Manifest();
|
|
mf.getMainAttributes().put(Name.MANIFEST_VERSION, "1.0");
|
|
mf.getEntries().put(SOME_KEY, new Attributes() {{
|
|
map.put(new Name(SOME_KEY), null);
|
|
}});
|
|
mf = writeAndRead(mf);
|
|
assertEquals(mf.getEntries().get(SOME_KEY).getValue(SOME_KEY),
|
|
NULL_TEXT);
|
|
}
|
|
|
|
@Test
|
|
public void testNamedSectionHeaderValueEmpty() throws IOException {
|
|
Manifest mf = new Manifest();
|
|
mf.getMainAttributes().put(Name.MANIFEST_VERSION, "1.0");
|
|
mf.getEntries().put(SOME_KEY, new Attributes() {{
|
|
map.put(new Name(SOME_KEY), EMPTY_STR);
|
|
}});
|
|
mf = writeAndRead(mf);
|
|
assertEquals(mf.getEntries().get(SOME_KEY).getValue(SOME_KEY),
|
|
EMPTY_STR);
|
|
}
|
|
|
|
static Manifest writeAndRead(Manifest mf) throws IOException {
|
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
mf.write(out);
|
|
byte[] mfBytes = out.toByteArray();
|
|
System.out.println("-".repeat(72));
|
|
System.out.print(new String(mfBytes, UTF_8));
|
|
System.out.println("-".repeat(72));
|
|
ByteArrayInputStream in = new ByteArrayInputStream(mfBytes);
|
|
return new Manifest(in);
|
|
}
|
|
|
|
}
|