/*************************GO-LICENSE-START********************************* * Copyright 2014 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. *************************GO-LICENSE-END***********************************/ package com.thoughtworks.studios.shine.cruise.stage; import java.io.File; import java.util.Arrays; import java.util.HashMap; import java.util.List; import com.thoughtworks.go.domain.StageIdentifier; import com.thoughtworks.go.server.dao.sparql.RdfResultMapper; import com.thoughtworks.go.util.TempFiles; import com.thoughtworks.studios.shine.cruise.GoOntology; import com.thoughtworks.studios.shine.cruise.stage.details.StageStorage; import com.thoughtworks.studios.shine.semweb.BoundVariables; import com.thoughtworks.studios.shine.semweb.Graph; import com.thoughtworks.studios.shine.semweb.TempGraphFactory; import com.thoughtworks.studios.shine.semweb.URIReference; import com.thoughtworks.studios.shine.semweb.sesame.InMemoryTempGraphFactory; import org.junit.After; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; public class StagesQueryTest { private StageStorage graphLoader; private TempGraphFactory graphFactory; private TempFiles tempFiles; @Before public void setUp() throws Exception { tempFiles = new TempFiles(); File tempFolder = tempFiles.createUniqueFolder("shine"); graphLoader = new StageStorage(tempFolder.getAbsolutePath()); graphLoader.clear(); graphFactory = new InMemoryTempGraphFactory(); } @After public void tearDown() { tempFiles.cleanUp(); } @Test public void testRunSparqlAgainstMultipleStagesWithEmptyCacheWillPopulateCache() { populateStage("p", 1, "s", 2, "http://job/1"); populateStage("p", 2, "s", 2, "http://job/2"); InMemoryCache cache = new InMemoryCache(); StagesQuery stagesQuery = new StagesQuery(graphLoader, cache); String sparql = "PREFIX cruise:<" + GoOntology.URI + ">" + "SELECT ?job WHERE {" + " ?job a cruise:Job . " + "}"; StageIdentifier stageIdentifierOne = new StageIdentifier("p", 1, "s", "2"); StageIdentifier stageIdentifierTwo = new StageIdentifier("p", 2, "s", "2"); List<TestModel> bvs = stagesQuery.select(sparql, Arrays.asList(stageIdentifierOne, stageIdentifierTwo), new RdfResultMapper<TestModel>() { public TestModel map(BoundVariables aRow) { return new TestModel(aRow.getAsString("job")); } }); assertEquals(2, bvs.size()); assertEquals(new TestModel("http://job/1"), bvs.get(0)); assertEquals(new TestModel("http://job/2"), bvs.get(1)); assertNotNull(cache.get(new StagesQueryCache.CacheKey(sparql, stageIdentifierOne))); assertNotNull(cache.get(new StagesQueryCache.CacheKey(sparql, stageIdentifierTwo))); } private static class TestModel { private final String job; public TestModel(String job) { this.job = job; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof TestModel)) { return false; } TestModel testModel = (TestModel) o; if (job != null ? !job.equals(testModel.job) : testModel.job != null) { return false; } return true; } @Override public int hashCode() { return job != null ? job.hashCode() : 0; } } @Test public void testQueryResultWillBeGetFromCacheIfCacheIsHit() { InMemoryCache cache = new InMemoryCache(); StagesQuery stagesQuery = new StagesQuery(graphLoader, cache); String sparql = "PREFIX cruise:<" + GoOntology.URI + ">" + "SELECT ?job WHERE {" + " ?job a cruise:Job . " + "}"; StageIdentifier stageIdentifier = new StageIdentifier("p", 1, "s", "2"); cache.put(Arrays.<BoundVariables>asList(new BoundVariablesStub("job", "http://job/1")), new StagesQueryCache.CacheKey(sparql, stageIdentifier)); List<BoundVariables> bvs = stagesQuery.select(sparql, Arrays.asList(stageIdentifier), new RdfResultMapper<BoundVariables>() { public BoundVariables map(BoundVariables aRow) { return aRow; } }); assertEquals(1, bvs.size()); assertEquals("http://job/1", bvs.get(0).getAsString("job")); } private void populateStage(String pipelineName, int pipelineCounter, String stageName, int stageCounter, String job) { graphLoader.save(graphWithRDF("" + "@prefix cruise: <" + GoOntology.URI + "> . " + "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . " + "@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . " + "" + "<http://pipeline/1> a cruise:Pipeline ." + "<http://pipeline/1> cruise:pipelineName \"" + pipelineName + "\"^^xsd:string ." + "<http://pipeline/1> cruise:pipelineCounter " + pipelineCounter + " ." + "<http://pipeline/1> cruise:hasStage <http://stage/1> ." + "<http://stage/1> rdf:type cruise:Stage . " + "<http://stage/1> cruise:stageName \"" + stageName + "\"^^xsd:string . " + "<http://stage/1> cruise:stageCounter " + stageCounter + " . " + "<http://stage/1> cruise:hasJob <" + job + "> . " + "<" + job + "> a cruise:Job . " + "")); } private Graph graphWithRDF(String rdf) { Graph graph = graphFactory.createTempGraph(); graph.addTriplesFromTurtle(rdf); return graph; } private class BoundVariablesStub implements BoundVariables { private String variable; private String value; public BoundVariablesStub(String variable, String value) { this.variable = variable; this.value = value; } public String getAsString(String boundName) { if (boundName.equals(variable)) { return value; } return null; } public Boolean getBoolean(String boundName) { return null; } public List<String> getBoundVariableNames() { return null; } public Integer getInt(String boundName) { return null; } public String getString(String boundName) { return null; } public URIReference getURIReference(String boundName) { return null; } } private class InMemoryCache extends HashMap<String, List> implements StagesQueryCache { public List get(CacheKey key) { return this.get(key.getKey()); } public void put(List boundVariables, CacheKey key) { this.put(key.getKey(), boundVariables); } } }