/* * Zed Attack Proxy (ZAP) and its related class files. * * ZAP is an HTTP/HTTPS proxy for assessing web application security. * * Copyright 2012 ZAP development team * * 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 org.zaproxy.zap.control; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.junit.Assert.*; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; import java.util.Collection; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine; import org.zaproxy.zap.utils.ZapXmlConfiguration; /** * Unit test for {@link AddOn}. */ public class AddOnUnitTest { @Rule public TemporaryFolder tempDir = new TemporaryFolder(); private static final File ZAP_VERSIONS_XML = Paths.get("test/resources/org/zaproxy/zap/control", "ZapVersions-deps.xml").toFile(); @Test @SuppressWarnings("deprecation") public void testIsAddon() throws Exception { assertTrue(AddOn.isAddOn("test-alpha-1.zap")); } @Test @SuppressWarnings("deprecation") public void testNotAddonNoState() throws Exception { assertFalse(AddOn.isAddOn("test-1.zap")); } @Test @SuppressWarnings("deprecation") public void testNotAddonBadExt() throws Exception { assertFalse(AddOn.isAddOn("test-beta-1.zip")); } @Test @SuppressWarnings("deprecation") public void testNotAddonBadStatus() throws Exception { assertFalse(AddOn.isAddOn("test-xxx-1.zap")); } @Test @SuppressWarnings("deprecation") public void testNotAddonBadVersion() throws Exception { assertFalse(AddOn.isAddOn("test-beta-A.zap")); } @Test @SuppressWarnings("deprecation") public void testId() throws Exception { AddOn addOn = new AddOn("test-alpha-1.zap"); assertThat(addOn.getId(), is("test")); } @Test @SuppressWarnings("deprecation") public void testStatus() throws Exception { AddOn addOn = new AddOn("test-alpha-1.zap"); assertThat(addOn.getStatus().name(), is("alpha")); } @Test @SuppressWarnings("deprecation") public void testVersion() throws Exception { AddOn addOn = new AddOn("test-alpha-1.zap"); assertThat(addOn.getFileVersion(), is(1)); } @Test @SuppressWarnings("deprecation") public void testAlpha2UpdatesAlpha1() throws Exception { AddOn addOnA1 = new AddOn("test-alpha-1.zap"); AddOn addOnA2 = new AddOn("test-alpha-2.zap"); assertTrue(addOnA2.isUpdateTo(addOnA1)); } @Test @SuppressWarnings("deprecation") public void testAlpha1DoesNotUpdateAlpha2() throws Exception { AddOn addOnA1 = new AddOn("test-alpha-1.zap"); AddOn addOnA2 = new AddOn("test-alpha-2.zap"); assertFalse(addOnA1.isUpdateTo(addOnA2)); } @Test @SuppressWarnings("deprecation") public void testAlpha2UpdatesBeta1() throws Exception { AddOn addOnB1 = new AddOn("test-beta-1.zap"); AddOn addOnA2 = new AddOn("test-alpha-2.zap"); assertTrue(addOnA2.isUpdateTo(addOnB1)); } @Test(expected = IllegalArgumentException.class) @SuppressWarnings("deprecation") public void testAlpha2DoesNotUpdateTestyAlpha1() throws Exception { // Given AddOn addOnA1 = new AddOn("test-alpha-1.zap"); AddOn addOnA2 = new AddOn("testy-alpha-2.zap"); // When addOnA2.isUpdateTo(addOnA1); // Then = Exception } @Test @SuppressWarnings("deprecation") public void testCanLoadAddOnNotBefore() throws Exception { AddOn ao = new AddOn("test-alpha-1.zap"); ao.setNotBeforeVersion("2.4.0"); assertTrue(ao.canLoadInVersion("2.4.0")); ao.setNotBeforeVersion("2.4.0"); assertTrue(ao.canLoadInVersion("2.4.0")); assertTrue(ao.canLoadInVersion("2.5.0")); assertFalse(ao.canLoadInVersion("1.4.0")); assertFalse(ao.canLoadInVersion("2.0.alpha")); } @Test @SuppressWarnings("deprecation") public void testCanLoadAddOnNotFrom() throws Exception { AddOn ao = new AddOn("test-alpha-1.zap"); ao.setNotBeforeVersion("2.4.0"); ao.setNotFromVersion("2.8.0"); assertTrue(ao.canLoadInVersion("2.4.0")); assertTrue(ao.canLoadInVersion("2.5.0")); assertTrue(ao.canLoadInVersion("2.7.0")); assertFalse(ao.canLoadInVersion("2.8.0")); assertFalse(ao.canLoadInVersion("2.8.0.1")); assertFalse(ao.canLoadInVersion("2.9.0")); } @Test @SuppressWarnings("deprecation") public void testCanLoadAddOnNotBeforeNotFrom() throws Exception { AddOn ao = new AddOn("test-alpha-1.zap"); ao.setNotBeforeVersion("2.4.0"); assertTrue(ao.canLoadInVersion("2.4.0")); ao.setNotFromVersion("2.7.0"); assertTrue(ao.canLoadInVersion("2.4.0")); assertTrue(ao.canLoadInVersion("2.5.0")); assertTrue(ao.canLoadInVersion("2.6.0")); assertFalse(ao.canLoadInVersion("2.7.0")); assertFalse(ao.canLoadInVersion("2.7.0.1")); assertFalse(ao.canLoadInVersion("2.8.0")); } @Test public void shouldNotBeAddOnFileNameIfNull() throws Exception { // Given String fileName = null; // When boolean addOnFileName = AddOn.isAddOnFileName(fileName); // Then assertThat(addOnFileName, is(equalTo(false))); } @Test public void shouldNotBeAddOnFileNameIfNotEndsWithZapExtension() throws Exception { // Given String fileName = "addon.txt"; // When boolean addOnFileName = AddOn.isAddOnFileName(fileName); // Then assertThat(addOnFileName, is(equalTo(false))); } @Test public void shouldBeAddOnFileNameIfEndsWithZapExtension() throws Exception { // Given String fileName = "addon.zap"; // When boolean addOnFileName = AddOn.isAddOnFileName(fileName); // Then assertThat(addOnFileName, is(equalTo(true))); } @Test public void shouldBeAddOnFileNameEvenIfZapExtensionIsUpperCase() throws Exception { // Given String fileName = "addon.ZAP"; // When boolean addOnFileName = AddOn.isAddOnFileName(fileName); // Then assertThat(addOnFileName, is(equalTo(true))); } @Test public void shouldNotBeAddOnIfPathIsNull() throws Exception { // Given Path file = null; // When boolean addOnFile = AddOn.isAddOn(file); // Then assertThat(addOnFile, is(equalTo(false))); } @Test public void shouldNotBeAddOnIfPathIsDirectory() throws Exception { // Given Path file = tempDir.newFolder("addon.zap").toPath(); // When boolean addOnFile = AddOn.isAddOn(file); // Then assertThat(addOnFile, is(equalTo(false))); } @Test public void shouldNotBeAddOnIfFileNameNotEndsWithZapExtension() throws Exception { // Given Path file = createAddOnFile("addon.txt", "alpha", "1"); // When boolean addOnFile = AddOn.isAddOn(file); // Then assertThat(addOnFile, is(equalTo(false))); } @Test public void shouldNotBeAddOnIfAddOnDoesNotHaveManifestFile() throws Exception { // Given Path file = createEmptyAddOnFile("addon.zap"); // When boolean addOnFile = AddOn.isAddOn(file); // Then assertThat(addOnFile, is(equalTo(false))); } @Test public void shouldBeAddOnIfPathEndsWithZapExtension() throws Exception { // Given Path file = createAddOnFile("addon.zap", "alpha", "1"); // When boolean addOnFile = AddOn.isAddOn(file); // Then assertThat(addOnFile, is(equalTo(true))); } @Test public void shouldBeAddOnEvenIfZapExtensionIsUpperCase() throws Exception { // Given Path file = createAddOnFile("addon.ZAP", "alpha", "1"); // When boolean addOnFile = AddOn.isAddOn(file); // Then assertThat(addOnFile, is(equalTo(true))); } @Test(expected = IOException.class) public void shouldFailToCreateAddOnFromNullFile() throws Exception { // Given Path file = null; // When new AddOn(file); // Then = IOException } @Test(expected = IOException.class) public void shouldFailToCreateAddOnFromFileWithInvalidFileName() throws Exception { // Given String invalidFileName = "addon.txt"; Path file = createAddOnFile(invalidFileName, "alpha", "1"); // When new AddOn(file); // Then = IOException } @Test public void shouldCreateAddOnFromFileAndUseManifestData() throws Exception { // Given Path file = createAddOnFile("addon.zap", "beta", "1"); // When AddOn addOn = new AddOn(file); // Then assertThat(addOn.getId(), is(equalTo("addon"))); assertThat(addOn.getStatus(), is(equalTo(AddOn.Status.beta))); assertThat(addOn.getFileVersion(), is(equalTo(1))); } @Test public void shouldIgnoreStatusInFileNameWhenCreatingAddOnFromFile() throws Exception { // Given Path file = createAddOnFile("addon-alpha.zap", "release", "1"); // When AddOn addOn = new AddOn(file); // Then assertThat(addOn.getStatus(), is(equalTo(AddOn.Status.release))); } @Test public void shouldIgnoreVersionInFileNameWhenCreatingAddOnFromFile() throws Exception { // Given Path file = createAddOnFile("addon-alpha-2.zap", "alpha", "3"); // When AddOn addOn = new AddOn(file); // Then assertThat(addOn.getFileVersion(), is(equalTo(3))); } @Test public void shouldReturnNormalisedFileName() throws Exception { // Given Path file = createAddOnFile("addon.zap", "alpha", "2"); AddOn addOn = new AddOn(file); // When String normalisedFileName = addOn.getNormalisedFileName(); // Then assertThat(normalisedFileName, is(equalTo("addon-2.zap"))); } @Test public void shouldDependOnDependency() throws Exception { // Given ZapXmlConfiguration zapVersionsXml = createZapVersionsXml(); AddOn addOn = createAddOn("AddOn1", zapVersionsXml); AddOn dependency = createAddOn("AddOn3", zapVersionsXml); // When boolean depends = addOn.dependsOn(dependency); // Then assertThat(depends, is(equalTo(true))); } @Test public void shouldNotDependIfNoDependencies() throws Exception { // Given AddOn addOn = new AddOn(createAddOnFile("AddOn-release-1.zap", "release", "1")); AddOn nonDependency = createAddOn("AddOn3", createZapVersionsXml()); // When boolean depends = addOn.dependsOn(nonDependency); // Then assertThat(depends, is(equalTo(false))); } @Test public void shouldNotDependOnNonDependency() throws Exception { // Given ZapXmlConfiguration zapVersionsXml = createZapVersionsXml(); AddOn addOn = createAddOn("AddOn9", zapVersionsXml); AddOn nonDependency = createAddOn("AddOn3", zapVersionsXml); // When boolean depends = addOn.dependsOn(nonDependency); // Then assertThat(depends, is(equalTo(false))); } @Test public void shouldNotDirectlyDependOnNonDirectDependency() throws Exception { // Given ZapXmlConfiguration zapVersionsXml = createZapVersionsXml(); AddOn addOn = createAddOn("AddOn1", zapVersionsXml); AddOn nonDirectDependency = createAddOn("AddOn8", zapVersionsXml); // When boolean depends = addOn.dependsOn(nonDirectDependency); // Then assertThat(depends, is(equalTo(false))); } @Test public void shouldNotDependOnItSelf() throws Exception { // Given ZapXmlConfiguration zapVersionsXml = createZapVersionsXml(); AddOn addOn = createAddOn("AddOn1", zapVersionsXml); AddOn sameAddOn = createAddOn("AddOn1", zapVersionsXml); // When boolean depends = addOn.dependsOn(sameAddOn); // Then assertThat(depends, is(equalTo(false))); } @Test public void shouldDependOnDependencies() throws Exception { // Given ZapXmlConfiguration zapVersionsXml = createZapVersionsXml(); AddOn addOn = createAddOn("AddOn1", zapVersionsXml); AddOn nonDependency = createAddOn("AddOn9", zapVersionsXml); AddOn dependency = createAddOn("AddOn3", zapVersionsXml); Collection<AddOn> addOns = Arrays.asList(new AddOn[] { nonDependency, dependency }); // When boolean depends = addOn.dependsOn(addOns); // Then assertThat(depends, is(equalTo(true))); } @Test public void shouldNotDirectlyDependOnNonDirectDependencies() throws Exception { // Given ZapXmlConfiguration zapVersionsXml = createZapVersionsXml(); AddOn addOn = createAddOn("AddOn1", zapVersionsXml); AddOn nonDependency = createAddOn("AddOn9", zapVersionsXml); AddOn nonDirectDependency = createAddOn("AddOn8", zapVersionsXml); Collection<AddOn> addOns = Arrays.asList(new AddOn[] { nonDependency, nonDirectDependency }); // When boolean depends = addOn.dependsOn(addOns); // Then assertThat(depends, is(equalTo(false))); } @Test public void shouldNotDependOnNonDependencies() throws Exception { // Given ZapXmlConfiguration zapVersionsXml = createZapVersionsXml(); AddOn addOn = createAddOn("AddOn1", zapVersionsXml); AddOn nonDependency1 = createAddOn("AddOn1", zapVersionsXml); AddOn nonDependency2 = createAddOn("AddOn9", zapVersionsXml); Collection<AddOn> addOns = Arrays.asList(new AddOn[] { nonDependency1, nonDependency2 }); // When boolean depends = addOn.dependsOn(addOns); // Then assertThat(depends, is(equalTo(false))); } private static ZapXmlConfiguration createZapVersionsXml() throws Exception { ZapXmlConfiguration zapVersionsXml = new ZapXmlConfiguration(ZAP_VERSIONS_XML); zapVersionsXml.setExpressionEngine(new XPathExpressionEngine()); return zapVersionsXml; } private Path createEmptyAddOnFile(String fileName) { try { File file = tempDir.newFile(fileName); new ZipOutputStream(new FileOutputStream(file)).close(); return file.toPath(); } catch (IOException e) { throw new RuntimeException(e); } } private Path createAddOnFile(String fileName, String status, String version) { try { File file = tempDir.newFile(fileName); try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(file))) { ZipEntry manifest = new ZipEntry(AddOn.MANIFEST_FILE_NAME); zos.putNextEntry(manifest); StringBuilder strBuilder = new StringBuilder(150); strBuilder.append("<zapaddon>"); strBuilder.append("<version>").append(version).append("</version>"); strBuilder.append("<status>").append(status).append("</status>"); strBuilder.append("</zapaddon>"); byte[] bytes = strBuilder.toString().getBytes(StandardCharsets.UTF_8); zos.write(bytes, 0, bytes.length); zos.closeEntry(); } return file.toPath(); } catch (IOException e) { throw new RuntimeException(e); } } protected static AddOn createAddOn(String addOnId, ZapXmlConfiguration zapVersions) throws Exception { return new AddOn(addOnId, Paths.get("").toFile(), zapVersions.configurationAt("addon_" + addOnId)); } }