/*
* Copyright 2017 ThoughtWorks, Inc.
*
* 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 com.thoughtworks.go.plugin.access.packagematerial;
import com.thoughtworks.go.plugin.access.common.settings.PluginSettingsConfiguration;
import com.thoughtworks.go.plugin.access.common.settings.PluginSettingsConstants;
import com.thoughtworks.go.plugin.access.common.settings.PluginSettingsJsonMessageHandler1_0;
import com.thoughtworks.go.plugin.api.config.Property;
import com.thoughtworks.go.plugin.api.material.packagerepository.PackageMaterialProperty;
import com.thoughtworks.go.plugin.api.material.packagerepository.PackageRevision;
import com.thoughtworks.go.plugin.api.material.packagerepository.RepositoryConfiguration;
import com.thoughtworks.go.plugin.api.request.GoPluginApiRequest;
import com.thoughtworks.go.plugin.api.response.DefaultGoPluginApiResponse;
import com.thoughtworks.go.plugin.api.response.Result;
import com.thoughtworks.go.plugin.api.response.validation.ValidationError;
import com.thoughtworks.go.plugin.api.response.validation.ValidationResult;
import com.thoughtworks.go.plugin.infra.PluginManager;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import static com.thoughtworks.go.plugin.access.packagematerial.PackageRepositoryExtension.EXTENSION_NAME;
import static java.util.Arrays.asList;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
public class PackageRepositoryExtensionTest {
public static final String PLUGIN_ID = "plugin-id";
public static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
@Mock
private PluginManager pluginManager;
@Mock
private PluginSettingsJsonMessageHandler1_0 pluginSettingsJSONMessageHandler;
@Mock
private JsonMessageHandler1_0 jsonMessageHandler;
private PackageRepositoryExtension extension;
private PluginSettingsConfiguration pluginSettingsConfiguration;
private RepositoryConfiguration repositoryConfiguration;
private com.thoughtworks.go.plugin.api.material.packagerepository.PackageConfiguration packageConfiguration;
private ArgumentCaptor<GoPluginApiRequest> requestArgumentCaptor;
@Before
public void setUp() throws Exception {
initMocks(this);
extension = new PackageRepositoryExtension(pluginManager);
pluginSettingsConfiguration = new PluginSettingsConfiguration();
repositoryConfiguration = new RepositoryConfiguration();
repositoryConfiguration.add(new PackageMaterialProperty("key-one", "value-one"));
repositoryConfiguration.add(new PackageMaterialProperty("key-two", "value-two"));
packageConfiguration = new com.thoughtworks.go.plugin.api.material.packagerepository.PackageConfiguration();
packageConfiguration.add(new PackageMaterialProperty("key-three", "value-three"));
packageConfiguration.add(new PackageMaterialProperty("key-four", "value-four"));
requestArgumentCaptor = ArgumentCaptor.forClass(GoPluginApiRequest.class);
when(pluginManager.resolveExtensionVersion(PLUGIN_ID, asList("1.0"))).thenReturn("1.0");
}
@Test
public void shouldTalkToPluginToGetPluginSettingsConfiguration() throws Exception {
extension.registerHandler("1.0", pluginSettingsJSONMessageHandler);
extension.messageHandlerMap.put("1.0", jsonMessageHandler);
String responseBody = "expected-response";
PluginSettingsConfiguration deserializedResponse = new PluginSettingsConfiguration();
when(pluginSettingsJSONMessageHandler.responseMessageForPluginSettingsConfiguration(responseBody)).thenReturn(deserializedResponse);
when(pluginManager.isPluginOfType(EXTENSION_NAME, PLUGIN_ID)).thenReturn(true);
when(pluginManager.submitTo(eq(PLUGIN_ID), requestArgumentCaptor.capture())).thenReturn(DefaultGoPluginApiResponse.success(responseBody));
PluginSettingsConfiguration response = extension.getPluginSettingsConfiguration(PLUGIN_ID);
assertRequest(requestArgumentCaptor.getValue(), EXTENSION_NAME, "1.0", PluginSettingsConstants.REQUEST_PLUGIN_SETTINGS_CONFIGURATION, null);
verify(pluginSettingsJSONMessageHandler).responseMessageForPluginSettingsConfiguration(responseBody);
assertSame(response, deserializedResponse);
}
@Test
public void shouldTalkToPluginToGetPluginSettingsView() throws Exception {
extension.registerHandler("1.0", pluginSettingsJSONMessageHandler);
extension.messageHandlerMap.put("1.0", jsonMessageHandler);
String responseBody = "expected-response";
String deserializedResponse = "";
when(pluginSettingsJSONMessageHandler.responseMessageForPluginSettingsView(responseBody)).thenReturn(deserializedResponse);
when(pluginManager.isPluginOfType(EXTENSION_NAME, PLUGIN_ID)).thenReturn(true);
when(pluginManager.submitTo(eq(PLUGIN_ID), requestArgumentCaptor.capture())).thenReturn(DefaultGoPluginApiResponse.success(responseBody));
String response = extension.getPluginSettingsView(PLUGIN_ID);
assertRequest(requestArgumentCaptor.getValue(), EXTENSION_NAME, "1.0", PluginSettingsConstants.REQUEST_PLUGIN_SETTINGS_VIEW, null);
verify(pluginSettingsJSONMessageHandler).responseMessageForPluginSettingsView(responseBody);
assertSame(response, deserializedResponse);
}
@Test
public void shouldTalkToPluginToValidatePluginSettings() throws Exception {
extension.registerHandler("1.0", pluginSettingsJSONMessageHandler);
extension.messageHandlerMap.put("1.0", jsonMessageHandler);
String requestBody = "expected-request";
when(pluginSettingsJSONMessageHandler.requestMessageForPluginSettingsValidation(pluginSettingsConfiguration)).thenReturn(requestBody);
String responseBody = "expected-response";
ValidationResult deserializedResponse = new ValidationResult();
when(pluginSettingsJSONMessageHandler.responseMessageForPluginSettingsValidation(responseBody)).thenReturn(deserializedResponse);
when(pluginManager.isPluginOfType(EXTENSION_NAME, PLUGIN_ID)).thenReturn(true);
when(pluginManager.submitTo(eq(PLUGIN_ID), requestArgumentCaptor.capture())).thenReturn(DefaultGoPluginApiResponse.success(responseBody));
ValidationResult response = extension.validatePluginSettings(PLUGIN_ID, pluginSettingsConfiguration);
assertRequest(requestArgumentCaptor.getValue(), EXTENSION_NAME, "1.0", PluginSettingsConstants.REQUEST_VALIDATE_PLUGIN_SETTINGS, requestBody);
verify(pluginSettingsJSONMessageHandler).responseMessageForPluginSettingsValidation(responseBody);
assertSame(response, deserializedResponse);
}
@Test
public void shouldTalkToPluginToGetRepositoryConfiguration() throws Exception {
String expectedRequestBody = null;
String expectedResponseBody = "{" +
"\"key-one\":{}," +
"\"key-two\":{\"default-value\":\"two\",\"part-of-identity\":true,\"secure\":true,\"required\":true,\"display-name\":\"display-two\",\"display-order\":\"1\"}," +
"\"key-three\":{\"default-value\":\"three\",\"part-of-identity\":false,\"secure\":false,\"required\":false,\"display-name\":\"display-three\",\"display-order\":\"2\"}" +
"}";
when(pluginManager.isPluginOfType(EXTENSION_NAME, PLUGIN_ID)).thenReturn(true);
when(pluginManager.submitTo(eq(PLUGIN_ID), requestArgumentCaptor.capture())).thenReturn(DefaultGoPluginApiResponse.success(expectedResponseBody));
RepositoryConfiguration repositoryConfiguration = extension.getRepositoryConfiguration(PLUGIN_ID);
assertRequest(requestArgumentCaptor.getValue(), EXTENSION_NAME, "1.0", PackageRepositoryExtension.REQUEST_REPOSITORY_CONFIGURATION, expectedRequestBody);
assertPropertyConfiguration((PackageMaterialProperty) repositoryConfiguration.get("key-one"), "key-one", null, true, true, false, "", 0);
assertPropertyConfiguration((PackageMaterialProperty) repositoryConfiguration.get("key-two"), "key-two", "two", true, true, true, "display-two", 1);
assertPropertyConfiguration((PackageMaterialProperty) repositoryConfiguration.get("key-three"), "key-three", "three", false, false, false, "display-three", 2);
}
@Test
public void shouldTalkToPluginToGetPackageConfiguration() throws Exception {
String expectedRequestBody = null;
String expectedResponseBody = "{" +
"\"key-one\":{}," +
"\"key-two\":{\"default-value\":\"two\",\"part-of-identity\":true,\"secure\":true,\"required\":true,\"display-name\":\"display-two\",\"display-order\":\"1\"}," +
"\"key-three\":{\"default-value\":\"three\",\"part-of-identity\":false,\"secure\":false,\"required\":false,\"display-name\":\"display-three\",\"display-order\":\"2\"}" +
"}";
when(pluginManager.isPluginOfType(EXTENSION_NAME, PLUGIN_ID)).thenReturn(true);
when(pluginManager.submitTo(eq(PLUGIN_ID), requestArgumentCaptor.capture())).thenReturn(DefaultGoPluginApiResponse.success(expectedResponseBody));
com.thoughtworks.go.plugin.api.material.packagerepository.PackageConfiguration packageConfiguration = extension.getPackageConfiguration(PLUGIN_ID);
assertRequest(requestArgumentCaptor.getValue(), EXTENSION_NAME, "1.0", PackageRepositoryExtension.REQUEST_PACKAGE_CONFIGURATION, expectedRequestBody);
assertPropertyConfiguration((PackageMaterialProperty) packageConfiguration.get("key-one"), "key-one", null, true, true, false, "", 0);
assertPropertyConfiguration((PackageMaterialProperty) packageConfiguration.get("key-two"), "key-two", "two", true, true, true, "display-two", 1);
assertPropertyConfiguration((PackageMaterialProperty) packageConfiguration.get("key-three"), "key-three", "three", false, false, false, "display-three", 2);
}
@Test
public void shouldTalkToPluginToCheckIfRepositoryConfigurationIsValid() throws Exception {
String expectedRequestBody = "{\"repository-configuration\":{\"key-one\":{\"value\":\"value-one\"},\"key-two\":{\"value\":\"value-two\"}}}";
String expectedResponseBody = "[{\"key\":\"key-one\",\"message\":\"incorrect value\"},{\"message\":\"general error\"}]";
when(pluginManager.isPluginOfType(EXTENSION_NAME, PLUGIN_ID)).thenReturn(true);
when(pluginManager.submitTo(eq(PLUGIN_ID), requestArgumentCaptor.capture())).thenReturn(DefaultGoPluginApiResponse.success(expectedResponseBody));
ValidationResult validationResult = extension.isRepositoryConfigurationValid(PLUGIN_ID, repositoryConfiguration);
assertRequest(requestArgumentCaptor.getValue(), EXTENSION_NAME, "1.0", PackageRepositoryExtension.REQUEST_VALIDATE_REPOSITORY_CONFIGURATION, expectedRequestBody);
assertValidationError(validationResult.getErrors().get(0), "key-one", "incorrect value");
assertValidationError(validationResult.getErrors().get(1), "", "general error");
}
@Test
public void shouldTalkToPluginToCheckIfPackageConfigurationIsValid() throws Exception {
String expectedRequestBody = "{\"repository-configuration\":{\"key-one\":{\"value\":\"value-one\"},\"key-two\":{\"value\":\"value-two\"}}," +
"\"package-configuration\":{\"key-three\":{\"value\":\"value-three\"},\"key-four\":{\"value\":\"value-four\"}}}";
String expectedResponseBody = "[{\"key\":\"key-one\",\"message\":\"incorrect value\"},{\"message\":\"general error\"}]";
when(pluginManager.isPluginOfType(EXTENSION_NAME, PLUGIN_ID)).thenReturn(true);
when(pluginManager.submitTo(eq(PLUGIN_ID), requestArgumentCaptor.capture())).thenReturn(DefaultGoPluginApiResponse.success(expectedResponseBody));
ValidationResult validationResult = extension.isPackageConfigurationValid(PLUGIN_ID, packageConfiguration, repositoryConfiguration);
assertRequest(requestArgumentCaptor.getValue(), EXTENSION_NAME, "1.0", PackageRepositoryExtension.REQUEST_VALIDATE_PACKAGE_CONFIGURATION, expectedRequestBody);
assertValidationError(validationResult.getErrors().get(0), "key-one", "incorrect value");
assertValidationError(validationResult.getErrors().get(1), "", "general error");
}
@Test
public void shouldTalkToPluginToGetLatestModification() throws Exception {
String expectedRequestBody = "{\"repository-configuration\":{\"key-one\":{\"value\":\"value-one\"},\"key-two\":{\"value\":\"value-two\"}}," +
"\"package-configuration\":{\"key-three\":{\"value\":\"value-three\"},\"key-four\":{\"value\":\"value-four\"}}}";
String expectedResponseBody = "{\"revision\":\"abc.rpm\",\"timestamp\":\"2011-07-14T19:43:37.100Z\",\"user\":\"some-user\",\"revisionComment\":\"comment\"," +
"\"trackbackUrl\":\"http:\\\\localhost:9999\",\"data\":{\"dataKeyOne\":\"data-value-one\",\"dataKeyTwo\":\"data-value-two\"}}";
when(pluginManager.isPluginOfType(EXTENSION_NAME, PLUGIN_ID)).thenReturn(true);
when(pluginManager.submitTo(eq(PLUGIN_ID), requestArgumentCaptor.capture())).thenReturn(DefaultGoPluginApiResponse.success(expectedResponseBody));
PackageRevision packageRevision = extension.getLatestRevision(PLUGIN_ID, packageConfiguration, repositoryConfiguration);
assertRequest(requestArgumentCaptor.getValue(), EXTENSION_NAME, "1.0", PackageRepositoryExtension.REQUEST_LATEST_REVISION, expectedRequestBody);
assertPackageRevision(packageRevision, "abc.rpm", "some-user", "2011-07-14T19:43:37.100Z", "comment", "http:\\localhost:9999");
}
@Test
public void shouldTalkToPluginToGetLatestModificationSinceLastRevision() throws Exception {
String expectedRequestBody = "{\"repository-configuration\":{\"key-one\":{\"value\":\"value-one\"},\"key-two\":{\"value\":\"value-two\"}}," +
"\"package-configuration\":{\"key-three\":{\"value\":\"value-three\"},\"key-four\":{\"value\":\"value-four\"}}," +
"\"previous-revision\":{\"revision\":\"abc.rpm\",\"timestamp\":\"2011-07-13T19:43:37.100Z\",\"data\":{\"dataKeyOne\":\"data-value-one\",\"dataKeyTwo\":\"data-value-two\"}}}";
String expectedResponseBody = "{\"revision\":\"abc.rpm\",\"timestamp\":\"2011-07-14T19:43:37.100Z\",\"user\":\"some-user\",\"revisionComment\":\"comment\"," +
"\"trackbackUrl\":\"http:\\\\localhost:9999\",\"data\":{\"dataKeyOne\":\"data-value-one\",\"dataKeyTwo\":\"data-value-two\"}}";
Date timestamp = new SimpleDateFormat(DATE_FORMAT).parse("2011-07-13T19:43:37.100Z");
Map data = new LinkedHashMap();
data.put("dataKeyOne", "data-value-one");
data.put("dataKeyTwo", "data-value-two");
PackageRevision previouslyKnownRevision = new PackageRevision("abc.rpm", timestamp, "someuser", "comment", null, data);
when(pluginManager.isPluginOfType(EXTENSION_NAME, PLUGIN_ID)).thenReturn(true);
when(pluginManager.submitTo(eq(PLUGIN_ID), requestArgumentCaptor.capture())).thenReturn(DefaultGoPluginApiResponse.success(expectedResponseBody));
PackageRevision packageRevision = extension.latestModificationSince(PLUGIN_ID, packageConfiguration, repositoryConfiguration, previouslyKnownRevision);
assertRequest(requestArgumentCaptor.getValue(), EXTENSION_NAME, "1.0", PackageRepositoryExtension.REQUEST_LATEST_REVISION_SINCE, expectedRequestBody);
assertPackageRevision(packageRevision, "abc.rpm", "some-user", "2011-07-14T19:43:37.100Z", "comment", "http:\\localhost:9999");
}
@Test
public void shouldTalkToPluginToCheckRepositoryConnectionSuccessful() throws Exception {
String expectedRequestBody = "{\"repository-configuration\":{\"key-one\":{\"value\":\"value-one\"},\"key-two\":{\"value\":\"value-two\"}}}";
String expectedResponseBody = "{\"status\":\"success\",messages=[\"message-one\",\"message-two\"]}";
when(pluginManager.isPluginOfType(EXTENSION_NAME, PLUGIN_ID)).thenReturn(true);
when(pluginManager.submitTo(eq(PLUGIN_ID), requestArgumentCaptor.capture())).thenReturn(DefaultGoPluginApiResponse.success(expectedResponseBody));
Result result = extension.checkConnectionToRepository(PLUGIN_ID, repositoryConfiguration);
assertRequest(requestArgumentCaptor.getValue(), EXTENSION_NAME, "1.0", PackageRepositoryExtension.REQUEST_CHECK_REPOSITORY_CONNECTION, expectedRequestBody);
assertSuccessResult(result, asList("message-one", "message-two"));
}
@Test
public void shouldTalkToPluginToCheckRepositoryConnectionFailure() throws Exception {
String expectedRequestBody = "{\"repository-configuration\":{\"key-one\":{\"value\":\"value-one\"},\"key-two\":{\"value\":\"value-two\"}}}";
String expectedResponseBody = "{\"status\":\"failed\",messages=[\"message-one\",\"message-two\"]}";
when(pluginManager.isPluginOfType(EXTENSION_NAME, PLUGIN_ID)).thenReturn(true);
when(pluginManager.submitTo(eq(PLUGIN_ID), requestArgumentCaptor.capture())).thenReturn(DefaultGoPluginApiResponse.success(expectedResponseBody));
Result result = extension.checkConnectionToRepository(PLUGIN_ID, repositoryConfiguration);
assertRequest(requestArgumentCaptor.getValue(), EXTENSION_NAME, "1.0", PackageRepositoryExtension.REQUEST_CHECK_REPOSITORY_CONNECTION, expectedRequestBody);
assertFailureResult(result, asList("message-one", "message-two"));
}
@Test
public void shouldTalkToPluginToCheckPackageConnectionSuccessful() throws Exception {
String expectedRequestBody = "{\"repository-configuration\":{\"key-one\":{\"value\":\"value-one\"},\"key-two\":{\"value\":\"value-two\"}}," +
"\"package-configuration\":{\"key-three\":{\"value\":\"value-three\"},\"key-four\":{\"value\":\"value-four\"}}}";
String expectedResponseBody = "{\"status\":\"success\",messages=[\"message-one\",\"message-two\"]}";
when(pluginManager.isPluginOfType(EXTENSION_NAME, PLUGIN_ID)).thenReturn(true);
when(pluginManager.submitTo(eq(PLUGIN_ID), requestArgumentCaptor.capture())).thenReturn(DefaultGoPluginApiResponse.success(expectedResponseBody));
Result result = extension.checkConnectionToPackage(PLUGIN_ID, packageConfiguration, repositoryConfiguration);
assertRequest(requestArgumentCaptor.getValue(), EXTENSION_NAME, "1.0", PackageRepositoryExtension.REQUEST_CHECK_PACKAGE_CONNECTION, expectedRequestBody);
assertSuccessResult(result, asList("message-one", "message-two"));
}
@Test
public void shouldTalkToPluginToCheckPackageConnectionFailure() throws Exception {
String expectedRequestBody = "{\"repository-configuration\":{\"key-one\":{\"value\":\"value-one\"},\"key-two\":{\"value\":\"value-two\"}}," +
"\"package-configuration\":{\"key-three\":{\"value\":\"value-three\"},\"key-four\":{\"value\":\"value-four\"}}}";
String expectedResponseBody = "{\"status\":\"failure\",messages=[\"message-one\",\"message-two\"]}";
when(pluginManager.isPluginOfType(EXTENSION_NAME, PLUGIN_ID)).thenReturn(true);
when(pluginManager.submitTo(eq(PLUGIN_ID), requestArgumentCaptor.capture())).thenReturn(DefaultGoPluginApiResponse.success(expectedResponseBody));
Result result = extension.checkConnectionToPackage(PLUGIN_ID, packageConfiguration, repositoryConfiguration);
assertRequest(requestArgumentCaptor.getValue(), EXTENSION_NAME, "1.0", PackageRepositoryExtension.REQUEST_CHECK_PACKAGE_CONNECTION, expectedRequestBody);
assertFailureResult(result, asList("message-one", "message-two"));
}
@Test
public void shouldHandleExceptionDuringPluginInteraction() throws Exception {
when(pluginManager.isPluginOfType(EXTENSION_NAME, PLUGIN_ID)).thenReturn(true);
when(pluginManager.submitTo(eq(PLUGIN_ID), requestArgumentCaptor.capture())).thenThrow(new RuntimeException("exception-from-plugin"));
try {
extension.checkConnectionToPackage(PLUGIN_ID, packageConfiguration, repositoryConfiguration);
} catch (Exception e) {
assertThat(e.getMessage(), is("Interaction with plugin with id 'plugin-id' implementing 'package-repository' extension failed while requesting for 'check-package-connection'. Reason: [exception-from-plugin]"));
}
}
private void assertPropertyConfiguration(PackageMaterialProperty property, String key, String value, boolean partOfIdentity, boolean required, boolean secure, String displayName, int displayOrder) {
assertThat(property.getKey(), is(key));
assertThat(property.getValue(), is(value));
assertThat(property.getOption(Property.PART_OF_IDENTITY), is(partOfIdentity));
assertThat(property.getOption(Property.REQUIRED), is(required));
assertThat(property.getOption(Property.SECURE), is(secure));
assertThat(property.getOption(Property.DISPLAY_NAME), is(displayName));
assertThat(property.getOption(Property.DISPLAY_ORDER), is(displayOrder));
}
private void assertRequest(GoPluginApiRequest goPluginApiRequest, String extensionName, String version, String requestName, String requestBody) {
assertThat(goPluginApiRequest.extension(), is(extensionName));
assertThat(goPluginApiRequest.extensionVersion(), is(version));
assertThat(goPluginApiRequest.requestName(), is(requestName));
assertThat(goPluginApiRequest.requestBody(), is(requestBody));
}
private void assertValidationError(ValidationError validationError, String expectedKey, String expectedMessage) {
assertThat(validationError.getKey(), is(expectedKey));
assertThat(validationError.getMessage(), is(expectedMessage));
}
private void assertPackageRevision(PackageRevision packageRevision, String revision, String user, String timestamp, String comment, String trackbackUrl) throws ParseException {
assertThat(packageRevision.getRevision(), is(revision));
assertThat(packageRevision.getUser(), is(user));
assertThat(packageRevision.getTimestamp(), is(new SimpleDateFormat(DATE_FORMAT).parse(timestamp)));
assertThat(packageRevision.getRevisionComment(), is(comment));
assertThat(packageRevision.getTrackbackUrl(), is(trackbackUrl));
assertThat(packageRevision.getData().size(), is(2));
assertThat(packageRevision.getDataFor("dataKeyOne"), is("data-value-one"));
assertThat(packageRevision.getDataFor("dataKeyTwo"), is("data-value-two"));
}
private void assertSuccessResult(Result result, List<String> messages) {
assertThat(result.isSuccessful(), is(true));
assertThat(result.getMessages(), is(messages));
}
private void assertFailureResult(Result result, List<String> messages) {
assertThat(result.isSuccessful(), is(false));
assertThat(result.getMessages(), is(messages));
}
}