/* * 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.server.dao; import java.sql.SQLException; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.sql.DataSource; import com.thoughtworks.go.domain.JobIdentifier; import com.thoughtworks.go.domain.Pipeline; import com.thoughtworks.go.domain.Properties; import com.thoughtworks.go.domain.Property; import com.thoughtworks.go.helper.PipelineMother; import org.hamcrest.Description; import org.hamcrest.TypeSafeMatcher; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import static com.thoughtworks.go.util.ListUtil.join; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNull.nullValue; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:WEB-INF/applicationContext-global.xml", "classpath:WEB-INF/applicationContext-dataLocalAccess.xml", "classpath:WEB-INF/applicationContext-acegi-security.xml" }) public class PropertyDaoTest { @Autowired private PropertyDao propertyDao; @Autowired private PipelineDao pipelineDao; @Autowired private DataSource dataSource; @Autowired private DatabaseAccessHelper dbHelper; private JobIdentifier pipeline1_1; private static final String PIPELINE1 = "pipeline"; private static final String STAGE1 = "stage"; private static final String PLAN1 = "plan"; private Long buildId; private static final String LABEL1 = "LABEL-1"; private static final JobIdentifier PIPELINE1_LABEL1 = new JobIdentifier(PIPELINE1, LABEL1, STAGE1, "LATEST", PLAN1, null); @Before public void setup() throws Exception { dbHelper.onSetUp(); pipeline1_1 = createPassedPipeline(); buildId = pipeline1_1.getBuildId(); } @After public void teardown() throws Exception { dbHelper.onTearDown(); } @Test public void shouldSavePropertyToDatabase() throws Exception { assertThat(propertyDao.save(buildId, property("name", "value")), is(true)); } @Test public void shouldNotSaveSameKeyWithSaveInstanceId() throws Exception { assertThat(propertyDao.save(buildId, property("name", "value1")), is(true)); assertThat(propertyDao.save(buildId, property("name", "value2")), is(false)); } @Test public void shouldSaveSameNameOnTwoInstances() throws Exception { JobIdentifier secondId = createPassedPipeline(); assertThat(propertyDao.save(buildId, property("name", "value1")), is(true)); assertThat(propertyDao.save(secondId.getBuildId(), property("name", "value2")), is(true)); } @Test public void shouldThrowExceptionWhenInstanceNotFound() throws Exception { long invalidId = buildId + 200L; try { propertyDao.save(invalidId, property("no.instance", "boo")); fail("Should not be able to save"); } catch (Exception expected) { assertThat(expected.getMessage(), is("No instance '" + invalidId + "' found to set property")); } } @Test public void shouldGetPropertyFromDatabase() throws Exception { propertyDao.save(buildId, property("name", "value1")); String value = propertyDao.value(buildId, "name"); assertThat(value, is("value1")); } @Test public void shouldReturnNullWhenPropertyNotInDatabase() throws Exception { String value = propertyDao.value(buildId, "not.directoryExists"); assertThat(value, is(nullValue())); } @Test public void shouldReturnListOfAllProperties() throws Exception { Property propertyB = property("a/2", "d"); Property propertyA = property("a/1", "b"); propertyDao.save(buildId, propertyB); propertyDao.save(buildId, propertyA); Properties properties = propertyDao.list(buildId); assertThat(properties.size(), is(2)); assertThat(properties.get(0), is(propertyA)); assertThat(properties.get(1), is(propertyB)); } @Test public void shouldLoadPropertiesHistoryLimitToSpecifiedCount() throws Exception { Pipeline oldPipeline = createPipelineWithJobProperty(PIPELINE1, property("key1", "value1")); Pipeline newPipeline = createPipelineWithJobProperty(PIPELINE1, property("key2", "value2")); List<Properties> history = propertyDao.loadHistory(PIPELINE1, STAGE1, PLAN1, newPipeline.getId(), 1); assertThat(history.size(), is(1)); assertThat(history.get(0).toString(), history.get(0).getValue("key2"), is("value2")); history = propertyDao.loadHistory(PIPELINE1, STAGE1, PLAN1, newPipeline.getId(), Integer.MAX_VALUE); assertThat(history.size(), is(2)); assertThat(history.get(0).toString(), history.get(0).getValue("key1"), is("value1")); assertThat(history.get(1).toString(), history.get(1).getValue("key2"), is("value2")); } @Test public void shouldLoadAllPropertiesHistoryIfLimitPipelineNotSpecified() throws Exception { Pipeline oldPipeline = createPipelineWithJobProperty(PIPELINE1, property("key1", "value1")); Pipeline newPipeline = createPipelineWithJobProperty(PIPELINE1, property("key2", "value2")); List<Properties> history = propertyDao.loadHistory(PIPELINE1, STAGE1, PLAN1, null, Integer.MAX_VALUE); assertThat(history.size(), is(2)); } @Test public void shouldGroupByPipelineId() throws Exception { ArrayList<Map<String, Object>> flatHistory = new ArrayList<>(); flatHistory.add(new HashMap<String, Object>() { { put("PIPELINEID", "1"); put("KEY", "cruise_job_id"); put("VALUE", "1"); } }); flatHistory.add(new HashMap<String, Object>() { { put("PIPELINEID", "1"); put("KEY", "cruise_agent"); put("VALUE", "agent1"); } }); flatHistory.add(new HashMap<String, Object>() { { put("PIPELINEID", "2"); put("KEY", "cruise_job_id"); put("VALUE", "2"); } }); flatHistory.add(new HashMap<String, Object>() { { put("PIPELINEID", "2"); put("KEY", "cruise_agent"); put("VALUE", "agent2"); } }); List<Properties> propertiesList = PropertySqlMapDao.groupByPipelineId(flatHistory); assertThat(propertiesList.size(), is(2)); assertThat(propertiesList.get(0).size(), is(2)); assertThat(propertiesList.get(0).getValue("cruise_agent"), is("agent1")); assertThat(propertiesList.get(1).size(), is(2)); assertThat(propertiesList.get(1).getValue("cruise_agent"), is("agent2")); } private JobIdentifier save(JobIdentifier jobIdentifier, Property prop) { propertyDao.save(jobIdentifier.getBuildId(), prop); return jobIdentifier; } private Property property(String key, String value) { return new Property(key, value); } private JobIdentifier createPassedPipeline() throws SQLException { return createPassedPipeline(PIPELINE1); } private JobIdentifier createPassedPipeline(String pipelineName) throws SQLException { Pipeline pipeline = _createPassedPipeline(pipelineName); return new JobIdentifier(pipeline, pipeline.getStages().get(0), pipeline.getStages().get(0).getJobInstances().get(0)); } private Pipeline _createPassedPipeline(String pipelineName) { Pipeline pipeline = PipelineMother.passedPipelineInstance(pipelineName, STAGE1, PLAN1); assertThat(pipeline.getStages().get(0).getJobInstances().size(), is(1)); pipeline.getStages().get(0).getJobInstances().get(0).setScheduledDate(new Date()); dbHelper.savePipelineWithStagesAndMaterials(pipeline); return pipeline; } private Pipeline createPipelineWithJobProperty(String pipelineName, Property property) { Pipeline pipeline = _createPassedPipeline(pipelineName); propertyDao.save(pipeline.getFirstStage().getJobInstances().first().getId(), property); return pipeline; } private TypeSafeMatcher<Properties> contains(final Property... properties) { return new TypeSafeMatcher<Properties>() { private final List<String> missingProps = new ArrayList<>(); public boolean matchesSafely(Properties item) { for (Property property : properties) { if (!item.contains(property)) { missingProps.add(property.toString()); } } return missingProps.isEmpty(); } public void describeTo(Description description) { description.appendText("contains [").appendText(join(missingProps)).appendText("]"); } }; } }