/** * Copyright 2012 Willet 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.willetinc.hadoop.mapreduce.dynamodb; import static org.easymock.EasyMock.*; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.mapreduce.Job; import org.junit.Test; import com.amazonaws.services.dynamodb.AmazonDynamoDBClient; import com.amazonaws.services.dynamodb.model.AttributeValue; import com.amazonaws.services.dynamodb.model.ComparisonOperator; import com.amazonaws.services.dynamodb.model.Key; import com.amazonaws.services.dynamodb.model.QueryRequest; import com.amazonaws.services.dynamodb.model.QueryResult; import com.willetinc.hadoop.mapreduce.dynamodb.DynamoDBConfiguration; import com.willetinc.hadoop.mapreduce.dynamodb.DynamoDBQueryRecordReader; import com.willetinc.hadoop.mapreduce.dynamodb.DynamoDBRecordReader; import com.willetinc.hadoop.mapreduce.dynamodb.DynamoDBQueryInputFormat.DynamoDBQueryInputSplit; public class DynamoDBQueryRecordReaderTest { private static final String TABLE_NAME = "clickstream-log"; private static final String ACCESS_KEY = "access_key"; private static final String SECRET_KEY = "secret_key"; @Test public void testConstructor() throws IOException { Job job = new Job(); Configuration conf = job.getConfiguration(); DynamoDBConfiguration.setCredentals(conf, ACCESS_KEY, SECRET_KEY); DynamoDBConfiguration dbConf = new DynamoDBConfiguration(conf); DynamoDBQueryInputSplit inputSplit = createStrictMock(DynamoDBQueryInputSplit.class); AmazonDynamoDBClient client = createStrictMock(AmazonDynamoDBClient.class); AttributeValue hashKeyValue = new AttributeValue().withN("007"); // the important thing we are testing here is that the range key condition // is not specified when the rangeKeyValues collection is empty expect(inputSplit.getHashKeyValue()).andReturn(hashKeyValue); expect(inputSplit.hasRangeKey()).andReturn(false); replay(inputSplit); replay(client); new DynamoDBQueryRecordReader<CSRecord>( inputSplit, CSRecord.class, conf, client, dbConf, TABLE_NAME); verify(inputSplit); verify(client); } @Test public void testConstructorWithRangeKey() throws IOException { Job job = new Job(); Configuration conf = job.getConfiguration(); DynamoDBConfiguration.setCredentals(conf, ACCESS_KEY, SECRET_KEY); DynamoDBConfiguration dbConf = new DynamoDBConfiguration(conf); DynamoDBQueryInputSplit inputSplit = createStrictMock(DynamoDBQueryInputSplit.class); AmazonDynamoDBClient client = createStrictMock(AmazonDynamoDBClient.class); AttributeValue hashKeyValue = new AttributeValue().withN("007"); List<AttributeValue> rangeKeyValues = new ArrayList<AttributeValue>(); rangeKeyValues.add(new AttributeValue().withN("1353121913437")); // the important thing we are testing here is that the range key condition // is specified when the rangeKey operator and values are specified expect(inputSplit.getHashKeyValue()).andReturn(hashKeyValue); expect(inputSplit.hasRangeKey()).andReturn(true); expect(inputSplit.getRangeKeyOperator()).andReturn(ComparisonOperator.EQ); expect(inputSplit.getRangeKeyValues()).andReturn(rangeKeyValues); replay(inputSplit); replay(client); new DynamoDBQueryRecordReader<CSRecord>( inputSplit, CSRecord.class, conf, client, dbConf, TABLE_NAME); verify(inputSplit); verify(client); } @Test public void testRecordReader() throws IOException, InterruptedException { Job job = new Job(); Configuration conf = job.getConfiguration(); DynamoDBConfiguration.setCredentals(conf, ACCESS_KEY, SECRET_KEY); DynamoDBConfiguration dbConf = new DynamoDBConfiguration(conf); DynamoDBQueryInputSplit inputSplit = createStrictMock(DynamoDBQueryInputSplit.class); AttributeValue hashKeyValue = new AttributeValue().withN("007"); AmazonDynamoDBClient client = createStrictMock(AmazonDynamoDBClient.class); QueryResult result = createStrictMock(QueryResult.class); Key lastKey = createStrictMock(Key.class); List<Map<String, AttributeValue>> list = new ArrayList<Map<String, AttributeValue>>(); Map<String, AttributeValue> value = new HashMap<String, AttributeValue>(); value.put("storeid", new AttributeValue().withN("22")); value.put("timestamp", new AttributeValue().withN("1353123945999")); value.put("clickstream", new AttributeValue().withS("673 713")); list.add(value); // first set of results expect(inputSplit.getHashKeyValue()).andReturn(hashKeyValue); expect(inputSplit.hasRangeKey()).andReturn(false); expect(client.query(anyObject(QueryRequest.class))).andReturn(result); expect(result.getLastEvaluatedKey()).andReturn(lastKey); expect(result.getItems()).andReturn(list); // second set of results expect(client.query(anyObject(QueryRequest.class))).andReturn(result); expect(result.getLastEvaluatedKey()).andReturn(null); expect(result.getItems()).andReturn(list); replay(inputSplit); replay(client); replay(result); replay(lastKey); DynamoDBRecordReader<CSRecord> reader = new DynamoDBQueryRecordReader<CSRecord>( inputSplit, CSRecord.class, conf, client, dbConf, TABLE_NAME); // first set of results assertTrue(reader.nextKeyValue()); assertEquals(0, reader.getCurrentKey().get()); // second set of results assertTrue(reader.nextKeyValue()); assertEquals(1, reader.getCurrentKey().get()); // no more results assertFalse(reader.nextKeyValue()); verify(inputSplit); verify(client); verify(result); verify(lastKey); } }