/*
* 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.examples.sportresults;
import co.cask.cdap.api.dataset.lib.PartitionDetail;
import co.cask.cdap.api.dataset.lib.PartitionKey;
import co.cask.cdap.api.dataset.lib.PartitionedFileSet;
import co.cask.cdap.test.ApplicationManager;
import co.cask.cdap.test.DataSetManager;
import co.cask.cdap.test.MapReduceManager;
import co.cask.cdap.test.ServiceManager;
import co.cask.cdap.test.TestBase;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableMap;
import jline.internal.InputStreamReader;
import org.apache.twill.filesystem.Location;
import org.junit.Assert;
import org.junit.Test;
import java.io.BufferedReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.sql.Connection;
import java.sql.ResultSet;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* Tests the functioning and completeness of the Sports app.
*/
public class SportResultsTest extends TestBase {
private static final String FANTASY_2014 =
"2014/1/3,My Team,Your Team,24,17\n" +
"2014/3/5,My Team,Other Team,17,16\n";
private static final String FANTASY_2015 =
"2015/3/10,Your Team,My Team,32,12\n" +
"2014/8/12,Other Team,Your Team,24,14\n";
private static final String CRITTERS_2014 =
"2015/3/10,Red Falcons,Blue Bonnets,28,17\n" +
"2014/8/12,Green Berets,Red Falcons,23,8\n";
@Test
public void testPartitionedCounting() throws Exception {
// deploy the application and start the upload service
ApplicationManager appManager = deployApplication(SportResults.class);
ServiceManager serviceManager = appManager.getServiceManager("UploadService").start();
serviceManager.waitForStatus(true);
// upload a few dummy results
URL url = serviceManager.getServiceURL();
uploadResults(url, "fantasy", 2014, FANTASY_2014);
uploadResults(url, "fantasy", 2015, FANTASY_2015);
uploadResults(url, "critters", 2014, CRITTERS_2014);
// start a map/reduce that counts all seasons for the fantasy league
MapReduceManager mrManager =
appManager.getMapReduceManager("ScoreCounter").start(ImmutableMap.of("league", "fantasy"));
mrManager.waitForFinish(5, TimeUnit.MINUTES); // should be much faster, though
// validate the output by reading directly from the file set
DataSetManager<PartitionedFileSet> dataSetManager = getDataset("totals");
PartitionedFileSet totals = dataSetManager.get();
PartitionDetail partitionDetail =
totals.getPartition(PartitionKey.builder().addStringField("league", "fantasy").build());
Assert.assertNotNull(partitionDetail);
Location location = partitionDetail.getLocation();
// find the part file that has the actual results
Assert.assertTrue(location.isDirectory());
for (Location file : location.list()) {
if (file.getName().startsWith("part")) {
location = file;
}
}
BufferedReader reader = new BufferedReader(new InputStreamReader(location.getInputStream()));
// validate each line
Map<String, String[]> expected = ImmutableMap.of(
"My Team", new String[] { "My Team", "2", "0", "1", "53", "65" },
"Your Team", new String[] { "Your Team", "1", "0", "2", "63", "60" },
"Other Team", new String[] { "Other Team", "1", "0", "1", "40", "31" });
while (true) {
String line = reader.readLine();
if (line == null) {
break;
}
String[] fields = line.split(",");
Assert.assertArrayEquals(expected.get(fields[0]), fields);
}
// verify using SQL
// query with SQL
Connection connection = getQueryClient();
ResultSet results = connection
.prepareStatement("SELECT wins, ties, losses, scored, conceded " +
"FROM dataset_totals WHERE team = 'My Team' AND league = 'fantasy'")
.executeQuery();
// should return only one row, with correct time fields
Assert.assertTrue(results.next());
Assert.assertEquals(2, results.getInt(1));
Assert.assertEquals(0, results.getInt(2));
Assert.assertEquals(1, results.getInt(3));
Assert.assertEquals(53, results.getInt(4));
Assert.assertEquals(65, results.getInt(5));
Assert.assertFalse(results.next());
}
// write a file to the file set using the service
private void uploadResults(URL url, String league, int season, String content) throws Exception {
HttpURLConnection connection = (HttpURLConnection)
new URL(url, String.format("leagues/%s/seasons/%d", league, season)).openConnection();
try {
connection.setDoOutput(true);
connection.setRequestMethod("PUT");
connection.getOutputStream().write(content.getBytes(Charsets.UTF_8));
Assert.assertEquals(HttpURLConnection.HTTP_OK, connection.getResponseCode());
} finally {
connection.disconnect();
}
}
}