/*
 *  Zed Attack Proxy (ZAP) and its related class files.
 *
 *  ZAP is an HTTP/HTTPS proxy for assessing web application security.
 *
 *  Copyright 2018 The 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.extension.wappalyzer;

import org.apache.commons.lang.StringUtils;
import org.junit.Test;
import org.mockito.Mockito;
import org.parosproxy.paros.model.HistoryReference;
import org.parosproxy.paros.model.SiteNode;
import org.parosproxy.paros.network.HttpMalformedHeaderException;
import org.parosproxy.paros.network.HttpMessage;
import org.zaproxy.zap.extension.pscanrulesAlpha.PassiveScannerTest;

import java.util.List;
import java.util.Optional;
import java.util.Vector;

import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.BDDMockito.given;

public class WappalyzerPassiveScannerUnitTest extends PassiveScannerTest<WappalyzerPassiveScanner> {

	WappalyzerApplicationTestHolder defaultHolder;

	public WappalyzerApplicationTestHolder getDefaultHolder() {
		if(defaultHolder == null){
			try {
				defaultHolder = new WappalyzerApplicationTestHolder();
				WappalyzerJsonParser parser = new WappalyzerJsonParser();
				WappalyzerData result = parser.parseDefaultAppsJson();
				defaultHolder.setApplications(result.getApplications());
			}catch(Exception ex){
				throw new RuntimeException(ex);
			}
		}
		return defaultHolder;
	}

	@Override
	protected void setUpMessages() {
		mockMessages(new ExtensionWappalyzer());
	}

	@Override
	protected WappalyzerPassiveScanner createScanner() {
		getDefaultHolder().resetApplicationsToSite();
		return new WappalyzerPassiveScanner(getDefaultHolder());
	}

    @Test
	public void testApacheWithPhp() throws HttpMalformedHeaderException {
		HttpMessage msg = makeHttpMessage();
		msg.setRequestHeader("GET https://www.example.com/test.php HTTP/1.1");
		msg.setResponseHeader(
				"HTTP/1.1 200 OK\r\n" +
				"Server: Apache\n" +
				"X-Powered-By: PHP/5.6.34");

		scan(msg);

		assertFoundAppCount("www.example.com:443", 2);
		assertFoundApp("www.example.com:443", "Apache");
		assertFoundApp("www.example.com:443", "PHP", "5.6.34");
	}

	@Test
	public void testModernizr() throws HttpMalformedHeaderException {
		HttpMessage msg = makeHttpMessage();
		msg.setResponseBody(
				"<html>" +
					"<script type='text/javascript' src='libs/modernizr.min.js?ver=4.1.1'>" +
					"</script>" +
				"</html>");
		scan(msg);

		assertFoundAppCount("www.example.com:443", 1);
		assertFoundApp("www.example.com:443", "Modernizr");
	}

	private void scan(HttpMessage msg) {
		rule.scanHttpResponseReceive(msg, -1, this.createSource(msg));
	}

	private HttpMessage makeHttpMessage() throws HttpMalformedHeaderException {
		HttpMessage httpMessage = new HttpMessage();
		SiteNode siteNode = Mockito.mock(SiteNode.class);
		given(siteNode.getPastHistoryReference()).willReturn(new Vector<>());

		HistoryReference ref = Mockito.mock(HistoryReference.class);
		given(ref.getSiteNode()).willReturn(siteNode);

		httpMessage.setHistoryRef(ref);

		httpMessage.setRequestHeader("GET https://www.example.com/ HTTP/1.1");
		httpMessage.setResponseHeader("HTTP/1.1 200 OK");
		return httpMessage;
	}

	private void assertFoundAppCount(String site, int appCount) {
		List<ApplicationMatch> appsForSite = getDefaultHolder().getAppsForSite(site);
		assertThat(appsForSite, notNullValue());
		assertThat(appsForSite.size(), is(appCount));
	}

	private void assertFoundApp(String site, String appName) {
		assertFoundApp(site, appName, null);
	}

	private void assertFoundApp(String site, String appName, String version) {
		List<ApplicationMatch> appsForSite = getDefaultHolder().getAppsForSite(site);
		assertThat(appsForSite, notNullValue());

		Optional<ApplicationMatch> app = appsForSite
				.stream()
				.filter(a -> StringUtils.equals(a.getApplication().getName(), appName))
				.findFirst();

		assertThat("Application '"+appName + "' not present", app.isPresent(), is(true));
		if(version != null){
			assertThat(app.get().getVersion(), is(version));
		}
	}
}

@@ -1124,33 +1124,17 @@
 zap.
-extension.pscanrulesAlpha
+testutils
 .Pas
@@ -1148,16 +1148,21 @@
 nnerTest
+Utils
 ;%0A%0Aimpor
@@ -1482,16 +1482,21 @@
 nnerTest
+Utils
 %3CWappaly

correct test class inheritance