/* * Copyright © 2015 Cask Data, 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 co.cask.cdap.test.app; import co.cask.cdap.api.dataset.lib.cube.AggregationFunction; import co.cask.cdap.api.dataset.lib.cube.CubeExploreQuery; import co.cask.cdap.api.dataset.lib.cube.CubeFact; import co.cask.cdap.api.dataset.lib.cube.CubeQuery; import co.cask.cdap.api.dataset.lib.cube.DimensionValue; import co.cask.cdap.api.dataset.lib.cube.MeasureType; import co.cask.cdap.api.dataset.lib.cube.TimeSeries; import co.cask.cdap.api.dataset.lib.cube.TimeValue; import co.cask.cdap.common.conf.Constants; import co.cask.cdap.test.ApplicationManager; import co.cask.cdap.test.ServiceManager; import co.cask.cdap.test.SlowTests; import co.cask.cdap.test.TestBase; import co.cask.cdap.test.TestConfiguration; import co.cask.common.http.HttpRequest; import co.cask.common.http.HttpRequests; import co.cask.common.http.HttpResponse; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import org.junit.Assert; import org.junit.ClassRule; import org.junit.Test; import org.junit.experimental.categories.Category; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.concurrent.TimeUnit; /** * */ public class TestAppWithCube extends TestBase { @ClassRule public static final TestConfiguration CONFIG = new TestConfiguration(Constants.Explore.EXPLORE_ENABLED, false); private static final Gson GSON = new Gson(); @Category(SlowTests.class) @Test public void testApp() throws Exception { // Deploy the application ApplicationManager appManager = deployApplication(AppWithCube.class); ServiceManager serviceManager = appManager.getServiceManager(AppWithCube.SERVICE_NAME).start(); try { serviceManager.waitForStatus(true); URL url = serviceManager.getServiceURL(); long tsInSec = System.currentTimeMillis() / 1000; // round to a minute for testing minute resolution tsInSec = (tsInSec / 60) * 60; // add couple facts add(url, ImmutableList.of(new CubeFact(tsInSec) .addDimensionValue("user", "alex").addDimensionValue("action", "click") .addMeasurement("count", MeasureType.COUNTER, 1))); add(url, ImmutableList.of(new CubeFact(tsInSec) .addDimensionValue("user", "alex").addDimensionValue("action", "click") .addMeasurement("count", MeasureType.COUNTER, 1), new CubeFact(tsInSec + 1) .addDimensionValue("user", "alex").addDimensionValue("action", "back") .addMeasurement("count", MeasureType.COUNTER, 1), new CubeFact(tsInSec + 2) .addDimensionValue("user", "alex").addDimensionValue("action", "click") .addMeasurement("count", MeasureType.COUNTER, 1))); // search for tags Collection<DimensionValue> tags = searchDimensionValue(url, new CubeExploreQuery(tsInSec - 60, tsInSec + 60, 1, 100, new ArrayList<DimensionValue>())); Assert.assertEquals(1, tags.size()); DimensionValue tv = tags.iterator().next(); Assert.assertEquals("user", tv.getName()); Assert.assertEquals("alex", tv.getValue()); tags = searchDimensionValue(url, CubeExploreQuery.builder() .from() .resolution(1, TimeUnit.SECONDS) .where() .dimension("user", "alex") .timeRange(tsInSec - 60, tsInSec + 60) .limit(100) .build()); Assert.assertEquals(2, tags.size()); Iterator<DimensionValue> iterator = tags.iterator(); tv = iterator.next(); Assert.assertEquals("action", tv.getName()); Assert.assertEquals("back", tv.getValue()); tv = iterator.next(); Assert.assertEquals("action", tv.getName()); Assert.assertEquals("click", tv.getValue()); // search for measures Collection<String> measures = searchMeasure(url, new CubeExploreQuery(tsInSec - 60, tsInSec + 60, 1, 100, ImmutableList.of(new DimensionValue("user", "alex")))); Assert.assertEquals(1, measures.size()); String measure = measures.iterator().next(); Assert.assertEquals("count", measure); // query for data // 1-sec resolution Collection<TimeSeries> data = query(url, CubeQuery.builder() .select() .measurement("count", AggregationFunction.SUM) .from(null) .resolution(1, TimeUnit.SECONDS) .where() .dimension("action", "click") .timeRange(tsInSec - 60, tsInSec + 60) .limit(100) .build()); Assert.assertEquals(1, data.size()); TimeSeries series = data.iterator().next(); List<TimeValue> timeValues = series.getTimeValues(); Assert.assertEquals(2, timeValues.size()); TimeValue timeValue = timeValues.get(0); Assert.assertEquals(tsInSec, timeValue.getTimestamp()); Assert.assertEquals(2, timeValue.getValue()); timeValue = timeValues.get(1); Assert.assertEquals(tsInSec + 2, timeValue.getTimestamp()); Assert.assertEquals(1, timeValue.getValue()); // 60-sec resolution data = query(url, new CubeQuery(null, tsInSec - 60, tsInSec + 60, 60, 100, ImmutableMap.of("count", AggregationFunction.SUM), ImmutableMap.of("action", "click"), new ArrayList<String>(), null)); Assert.assertEquals(1, data.size()); series = data.iterator().next(); timeValues = series.getTimeValues(); Assert.assertEquals(1, timeValues.size()); timeValue = timeValues.get(0); Assert.assertEquals(tsInSec, timeValue.getTimestamp()); Assert.assertEquals(3, timeValue.getValue()); } finally { serviceManager.stop(); serviceManager.waitForStatus(false); } } private void add(URL serviceUrl, Collection<CubeFact> facts) throws IOException { URL url = new URL(serviceUrl, "add"); HttpRequest request = HttpRequest.post(url).withBody(GSON.toJson(facts)).build(); HttpResponse response = HttpRequests.execute(request); Assert.assertEquals(200, response.getResponseCode()); } private Collection<DimensionValue> searchDimensionValue(URL serviceUrl, CubeExploreQuery query) throws IOException { URL url = new URL(serviceUrl, "searchDimensionValue"); HttpRequest request = HttpRequest.post(url).withBody(GSON.toJson(query)).build(); HttpResponse response = HttpRequests.execute(request); Assert.assertEquals(200, response.getResponseCode()); return GSON.fromJson(response.getResponseBodyAsString(), new TypeToken<Collection<DimensionValue>>() { }.getType()); } private Collection<String> searchMeasure(URL serviceUrl, CubeExploreQuery query) throws IOException { URL url = new URL(serviceUrl, "searchMeasure"); HttpRequest request = HttpRequest.post(url).withBody(GSON.toJson(query)).build(); HttpResponse response = HttpRequests.execute(request); Assert.assertEquals(200, response.getResponseCode()); return GSON.fromJson(response.getResponseBodyAsString(), new TypeToken<Collection<String>>() { }.getType()); } private Collection<TimeSeries> query(URL serviceUrl, CubeQuery query) throws IOException { URL url = new URL(serviceUrl, "query"); HttpRequest request = HttpRequest.post(url).withBody(GSON.toJson(query)).build(); HttpResponse response = HttpRequests.execute(request); Assert.assertEquals(200, response.getResponseCode()); return GSON.fromJson(response.getResponseBodyAsString(), new TypeToken<Collection<TimeSeries>>() { }.getType()); } }