/* * Copyright © 2016 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.client; import co.cask.cdap.api.app.Application; import co.cask.cdap.client.app.AllProgramsApp; import co.cask.cdap.client.common.ClientTestBase; import co.cask.cdap.client.config.ConnectionConfig; import co.cask.cdap.common.utils.Tasks; import co.cask.cdap.proto.Id; import co.cask.cdap.proto.ProgramStatus; import co.cask.cdap.proto.ProgramType; import co.cask.cdap.test.XSlowTests; import com.google.common.base.Charsets; import com.google.common.reflect.TypeToken; import com.google.gson.Gson; import org.junit.Assert; import org.junit.Test; import org.junit.experimental.categories.Category; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.lang.reflect.Type; import java.net.HttpURLConnection; import java.net.URL; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; /** * Tests for {@link co.cask.cdap.gateway.handlers.UsageHandler} */ @Category(XSlowTests.class) public class UsageHandlerTestRun extends ClientTestBase { private static final Gson GSON = new Gson(); private void deployApp(Class<? extends Application> appCls) throws Exception { new ApplicationClient(getClientConfig()).deploy(Id.Namespace.DEFAULT, createAppJarFile(appCls)); } private void deleteApp(Id.Application appId) throws Exception { new ApplicationClient(getClientConfig()).delete(appId); } private void startProgram(Id.Program programId) throws Exception { new ProgramClient(getClientConfig()).start(programId); } private void stopProgram(Id.Program programId) throws Exception { new ProgramClient(getClientConfig()).stop(programId); } private void waitState(final Id.Program programId, ProgramStatus status) throws Exception { final ProgramClient programclient = new ProgramClient(getClientConfig()); Tasks.waitFor(status, new Callable<ProgramStatus>() { @Override public ProgramStatus call() throws Exception { return ProgramStatus.valueOf(programclient.getStatus(programId)); } }, 60, TimeUnit.SECONDS, 100, TimeUnit.MILLISECONDS); } @Test public void testFlowUsage() throws Exception { final Id.Application app = Id.Application.from("default", AllProgramsApp.NAME); final Id.Program program = Id.Program.from(app, ProgramType.FLOW, AllProgramsApp.NoOpFlow.NAME); final Id.Stream stream = Id.Stream.from("default", AllProgramsApp.STREAM_NAME); final Id.DatasetInstance dataset = Id.DatasetInstance.from("default", AllProgramsApp.DATASET_NAME); Assert.assertEquals(0, getAppStreamUsage(app).size()); Assert.assertEquals(0, getProgramStreamUsage(program).size()); Assert.assertEquals(0, getStreamProgramUsage(stream).size()); Assert.assertEquals(0, getProgramDatasetUsage(program).size()); Assert.assertEquals(0, getAppDatasetUsage(app).size()); Assert.assertEquals(0, getDatasetProgramUsage(dataset).size()); deployApp(AllProgramsApp.class); try { Assert.assertTrue(getAppStreamUsage(app).contains(stream)); Assert.assertTrue(getProgramStreamUsage(program).contains(stream)); Assert.assertTrue(getStreamProgramUsage(stream).contains(program)); Assert.assertTrue(getProgramDatasetUsage(program).contains(dataset)); Assert.assertTrue(getAppDatasetUsage(app).contains(dataset)); Assert.assertTrue(getDatasetProgramUsage(dataset).contains(program)); } finally { deleteApp(app); Assert.assertEquals(0, getAppStreamUsage(app).size()); Assert.assertEquals(0, getProgramStreamUsage(program).size()); Assert.assertEquals(0, getStreamProgramUsage(stream).size()); } } @Test public void testWorkerUsage() throws Exception { final Id.Application app = Id.Application.from("default", AllProgramsApp.NAME); final Id.Program program = Id.Program.from(app, ProgramType.WORKER, AllProgramsApp.NoOpWorker.NAME); final Id.Stream stream = Id.Stream.from("default", AllProgramsApp.STREAM_NAME); final Id.DatasetInstance dataset = Id.DatasetInstance.from("default", AllProgramsApp.DATASET_NAME); Assert.assertEquals(0, getAppStreamUsage(app).size()); Assert.assertEquals(0, getProgramStreamUsage(program).size()); Assert.assertEquals(0, getStreamProgramUsage(stream).size()); Assert.assertEquals(0, getAppDatasetUsage(app).size()); Assert.assertEquals(0, getDatasetProgramUsage(dataset).size()); deployApp(AllProgramsApp.class); try { startProgram(program); waitState(program, ProgramStatus.RUNNING); stopProgram(program); waitState(program, ProgramStatus.STOPPED); Assert.assertTrue(getAppStreamUsage(app).contains(stream)); Assert.assertTrue(getProgramStreamUsage(program).contains(stream)); Assert.assertTrue(getStreamProgramUsage(stream).contains(program)); Assert.assertTrue(getProgramDatasetUsage(program).contains(dataset)); Assert.assertTrue(getAppDatasetUsage(app).contains(dataset)); Assert.assertTrue(getDatasetProgramUsage(dataset).contains(program)); } finally { deleteApp(app); Assert.assertEquals(0, getAppStreamUsage(app).size()); Assert.assertEquals(0, getProgramStreamUsage(program).size()); Assert.assertEquals(0, getStreamProgramUsage(stream).size()); Assert.assertEquals(0, getAppDatasetUsage(app).size()); Assert.assertEquals(0, getDatasetProgramUsage(dataset).size()); } } @Test public void testMapReduceUsage() throws Exception { final Id.Application app = Id.Application.from("default", AllProgramsApp.NAME); final Id.Program program = Id.Program.from(app, ProgramType.MAPREDUCE, AllProgramsApp.NoOpMR.NAME); final Id.Stream stream = Id.Stream.from("default", AllProgramsApp.STREAM_NAME); final Id.DatasetInstance dataset = Id.DatasetInstance.from("default", AllProgramsApp.DATASET_NAME); Assert.assertEquals(0, getAppStreamUsage(app).size()); Assert.assertEquals(0, getProgramStreamUsage(program).size()); Assert.assertEquals(0, getStreamProgramUsage(stream).size()); Assert.assertEquals(0, getAppDatasetUsage(app).size()); Assert.assertEquals(0, getDatasetProgramUsage(dataset).size()); deployApp(AllProgramsApp.class); try { Assert.assertTrue(getAppStreamUsage(app).contains(stream)); Assert.assertTrue(getProgramStreamUsage(program).contains(stream)); Assert.assertTrue(getStreamProgramUsage(stream).contains(program)); Assert.assertTrue(getProgramDatasetUsage(program).contains(dataset)); Assert.assertTrue(getAppDatasetUsage(app).contains(dataset)); Assert.assertTrue(getDatasetProgramUsage(dataset).contains(program)); } finally { deleteApp(app); Assert.assertEquals(0, getAppStreamUsage(app).size()); Assert.assertEquals(0, getProgramStreamUsage(program).size()); Assert.assertEquals(0, getStreamProgramUsage(stream).size()); Assert.assertEquals(0, getAppDatasetUsage(app).size()); Assert.assertEquals(0, getDatasetProgramUsage(dataset).size()); } } @Test public void testSparkUsage() throws Exception { final Id.Application app = Id.Application.from("default", AllProgramsApp.NAME); final Id.Program program = Id.Program.from(app, ProgramType.SPARK, AllProgramsApp.NoOpSpark.NAME); final Id.Stream stream = Id.Stream.from("default", AllProgramsApp.STREAM_NAME); final Id.DatasetInstance dataset = Id.DatasetInstance.from("default", AllProgramsApp.DATASET_NAME); Assert.assertEquals(0, getAppStreamUsage(app).size()); Assert.assertEquals(0, getProgramStreamUsage(program).size()); Assert.assertEquals(0, getStreamProgramUsage(stream).size()); Assert.assertEquals(0, getAppDatasetUsage(app).size()); Assert.assertEquals(0, getDatasetProgramUsage(dataset).size()); deployApp(AllProgramsApp.class); try { // the program will run and stop by itself. startProgram(program); waitState(program, ProgramStatus.STOPPED); Assert.assertTrue(getAppStreamUsage(app).contains(stream)); Assert.assertTrue(getProgramStreamUsage(program).contains(stream)); Assert.assertTrue(getStreamProgramUsage(stream).contains(program)); Assert.assertTrue(getProgramDatasetUsage(program).contains(dataset)); Assert.assertTrue(getAppDatasetUsage(app).contains(dataset)); Assert.assertTrue(getDatasetProgramUsage(dataset).contains(program)); } finally { deleteApp(app); Assert.assertEquals(0, getAppStreamUsage(app).size()); Assert.assertEquals(0, getProgramStreamUsage(program).size()); Assert.assertEquals(0, getStreamProgramUsage(stream).size()); Assert.assertEquals(0, getAppDatasetUsage(app).size()); Assert.assertEquals(0, getDatasetProgramUsage(dataset).size()); } } @Test public void testServiceUsage() throws Exception { final Id.Application app = Id.Application.from("default", AllProgramsApp.NAME); final Id.Program program = Id.Program.from(app, ProgramType.SERVICE, AllProgramsApp.NoOpService.NAME); final Id.DatasetInstance dataset = Id.DatasetInstance.from("default", AllProgramsApp.DATASET_NAME); Assert.assertEquals(0, getAppDatasetUsage(app).size()); Assert.assertEquals(0, getDatasetProgramUsage(dataset).size()); deployApp(AllProgramsApp.class); try { Assert.assertTrue(getProgramDatasetUsage(program).contains(dataset)); Assert.assertTrue(getAppDatasetUsage(app).contains(dataset)); Assert.assertTrue(getDatasetProgramUsage(dataset).contains(program)); } finally { deleteApp(app); Assert.assertEquals(0, getAppDatasetUsage(app).size()); Assert.assertEquals(0, getDatasetProgramUsage(dataset).size()); } } private <T> T doGet(String path, Type responseType) throws IOException { ConnectionConfig connectionConfig = getClientConfig().getConnectionConfig(); URL url = new URL(String.format("http://%s:%d%s", connectionConfig.getHostname(), connectionConfig.getPort(), path)); HttpURLConnection urlConn = (HttpURLConnection) url.openConnection(); try { Assert.assertEquals(200, urlConn.getResponseCode()); try (Reader reader = new BufferedReader(new InputStreamReader(urlConn.getInputStream(), Charsets.UTF_8))) { return GSON.fromJson(reader, responseType); } } finally { urlConn.disconnect(); } } private Set<Id.DatasetInstance> getAppDatasetUsage(Id.Application app) throws Exception { return doGet(String.format("/v3/namespaces/%s/apps/%s/datasets", app.getNamespaceId(), app.getId()), new TypeToken<Set<Id.DatasetInstance>>() { }.getType()); } private Set<Id.Stream> getAppStreamUsage(Id.Application app) throws Exception { return doGet(String.format("/v3/namespaces/%s/apps/%s/streams", app.getNamespaceId(), app.getId()), new TypeToken<Set<Id.Stream>>() { }.getType()); } private Set<Id.DatasetInstance> getProgramDatasetUsage(Id.Program program) throws Exception { return doGet(String.format("/v3/namespaces/%s/apps/%s/%s/%s/datasets", program.getNamespaceId(), program.getApplicationId(), program.getType().getCategoryName(), program.getId()), new TypeToken<Set<Id.DatasetInstance>>() { }.getType()); } private Set<Id.Stream> getProgramStreamUsage(Id.Program program) throws Exception { return doGet(String.format("/v3/namespaces/%s/apps/%s/%s/%s/streams", program.getNamespaceId(), program.getApplicationId(), program.getType().getCategoryName(), program.getId()), new TypeToken<Set<Id.Stream>>() { }.getType()); } // dataset/stream -> program private Set<Id.Program> getStreamProgramUsage(Id.Stream stream) throws Exception { return doGet(String.format("/v3/namespaces/%s/streams/%s/programs", stream.getNamespaceId(), stream.getId()), new TypeToken<Set<Id.Program>>() { }.getType()); } private Set<Id.Program> getDatasetProgramUsage(Id.DatasetInstance dataset) throws Exception { return doGet(String.format("/v3/namespaces/%s/data/datasets/%s/programs", dataset.getNamespaceId(), dataset.getId()), new TypeToken<Set<Id.Program>>() { }.getType()); } }