blob: b70cb00ec94f138ee5610d5c3505399e6b0df7a8 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.accumulo.core.client.mock;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import org.apache.accumulo.core.client.AccumuloException;
import org.apache.accumulo.core.client.AccumuloSecurityException;
import org.apache.accumulo.core.client.BatchDeleter;
import org.apache.accumulo.core.client.BatchScanner;
import org.apache.accumulo.core.client.BatchWriter;
import org.apache.accumulo.core.client.BatchWriterConfig;
import org.apache.accumulo.core.client.Connector;
import org.apache.accumulo.core.client.Instance;
import org.apache.accumulo.core.client.IteratorSetting;
import org.apache.accumulo.core.client.MultiTableBatchWriter;
import org.apache.accumulo.core.client.Scanner;
import org.apache.accumulo.core.client.security.tokens.PasswordToken;
import org.apache.accumulo.core.data.Key;
import org.apache.accumulo.core.data.Mutation;
import org.apache.accumulo.core.data.Range;
import org.apache.accumulo.core.data.Value;
import org.apache.accumulo.core.iterators.Combiner;
import org.apache.accumulo.core.iterators.user.SummingCombiner;
import org.apache.accumulo.core.security.Authorizations;
import org.apache.hadoop.io.Text;
import org.junit.Assert;
import org.junit.Test;
import com.google.common.collect.Iterators;
@Deprecated
public class MockConnectorTest {
Random random = new Random();
static Text asText(int i) {
return new Text(Integer.toHexString(i));
}
@Test
public void testSunnyDay() throws Exception {
Connector c = new MockConnector("root", new MockInstance());
c.tableOperations().create("test");
BatchWriter bw = c.createBatchWriter("test", new BatchWriterConfig());
for (int i = 0; i < 100; i++) {
int r = random.nextInt();
Mutation m = new Mutation(asText(r));
m.put(asText(random.nextInt()), asText(random.nextInt()), new Value(Integer.toHexString(r).getBytes()));
bw.addMutation(m);
}
bw.close();
BatchScanner s = c.createBatchScanner("test", Authorizations.EMPTY, 2);
s.setRanges(Collections.singletonList(new Range()));
Key key = null;
int count = 0;
for (Entry<Key,Value> entry : s) {
if (key != null)
assertTrue(key.compareTo(entry.getKey()) < 0);
assertEquals(entry.getKey().getRow(), new Text(entry.getValue().get()));
key = entry.getKey();
count++;
}
assertEquals(100, count);
}
@Test
public void testChangeAuths() throws Exception {
Connector c = new MockConnector("root", new MockInstance());
c.securityOperations().createLocalUser("greg", new PasswordToken(new byte[0]));
assertTrue(c.securityOperations().getUserAuthorizations("greg").isEmpty());
c.securityOperations().changeUserAuthorizations("greg", new Authorizations("A".getBytes()));
assertTrue(c.securityOperations().getUserAuthorizations("greg").contains("A".getBytes()));
c.securityOperations().changeUserAuthorizations("greg", new Authorizations("X", "Y", "Z"));
assertTrue(c.securityOperations().getUserAuthorizations("greg").contains("X".getBytes()));
assertFalse(c.securityOperations().getUserAuthorizations("greg").contains("A".getBytes()));
}
@Test
public void testBadMutations() throws Exception {
Connector c = new MockConnector("root", new MockInstance());
c.tableOperations().create("test");
BatchWriter bw = c
.createBatchWriter("test", new BatchWriterConfig().setMaxMemory(10000L).setMaxLatency(1000L, TimeUnit.MILLISECONDS).setMaxWriteThreads(4));
try {
bw.addMutation(null);
Assert.fail("addMutation should throw IAE for null mutation");
} catch (IllegalArgumentException iae) {}
try {
bw.addMutations(null);
Assert.fail("addMutations should throw IAE for null iterable");
} catch (IllegalArgumentException iae) {}
bw.addMutations(Collections.<Mutation> emptyList());
Mutation bad = new Mutation("bad");
try {
bw.addMutation(bad);
Assert.fail("addMutation should throw IAE for empty mutation");
} catch (IllegalArgumentException iae) {}
Mutation good = new Mutation("good");
good.put(asText(random.nextInt()), asText(random.nextInt()), new Value("good".getBytes()));
List<Mutation> mutations = new ArrayList<>();
mutations.add(good);
mutations.add(bad);
try {
bw.addMutations(mutations);
Assert.fail("addMutations should throw IAE if it contains empty mutation");
} catch (IllegalArgumentException iae) {}
bw.close();
}
@Test
public void testAggregation() throws Exception {
MockInstance mockInstance = new MockInstance();
Connector c = mockInstance.getConnector("root", new PasswordToken(""));
String table = "perDayCounts";
c.tableOperations().create(table);
IteratorSetting is = new IteratorSetting(10, "String Summation", SummingCombiner.class);
Combiner.setColumns(is, Collections.singletonList(new IteratorSetting.Column("day")));
SummingCombiner.setEncodingType(is, SummingCombiner.Type.STRING);
c.tableOperations().attachIterator(table, is);
String keys[][] = { {"foo", "day", "20080101"}, {"foo", "day", "20080101"}, {"foo", "day", "20080103"}, {"bar", "day", "20080101"},
{"bar", "day", "20080101"},};
BatchWriter bw = c.createBatchWriter("perDayCounts", new BatchWriterConfig());
for (String elt[] : keys) {
Mutation m = new Mutation(new Text(elt[0]));
m.put(new Text(elt[1]), new Text(elt[2]), new Value("1".getBytes()));
bw.addMutation(m);
}
bw.close();
Scanner s = c.createScanner("perDayCounts", Authorizations.EMPTY);
Iterator<Entry<Key,Value>> iterator = s.iterator();
assertTrue(iterator.hasNext());
checkEntry(iterator.next(), "bar", "day", "20080101", "2");
assertTrue(iterator.hasNext());
checkEntry(iterator.next(), "foo", "day", "20080101", "2");
assertTrue(iterator.hasNext());
checkEntry(iterator.next(), "foo", "day", "20080103", "1");
assertFalse(iterator.hasNext());
}
@Test
public void testDelete() throws Exception {
Connector c = new MockConnector("root", new MockInstance());
c.tableOperations().create("test");
BatchWriter bw = c.createBatchWriter("test", new BatchWriterConfig());
Mutation m1 = new Mutation("r1");
m1.put("cf1", "cq1", 1, "v1");
bw.addMutation(m1);
bw.flush();
Mutation m2 = new Mutation("r1");
m2.putDelete("cf1", "cq1", 2);
bw.addMutation(m2);
bw.flush();
Scanner scanner = c.createScanner("test", Authorizations.EMPTY);
int count = Iterators.size(scanner.iterator());
assertEquals(0, count);
try {
c.tableOperations().create("test_this_$tableName");
assertTrue(false);
} catch (IllegalArgumentException iae) {
}
}
@Test
public void testDeletewithBatchDeleter() throws Exception {
Connector c = new MockConnector("root", new MockInstance());
// make sure we are using a clean table
if (c.tableOperations().exists("test"))
c.tableOperations().delete("test");
c.tableOperations().create("test");
BatchDeleter deleter = c.createBatchDeleter("test", Authorizations.EMPTY, 2, new BatchWriterConfig());
// first make sure it deletes fine when its empty
deleter.setRanges(Collections.singletonList(new Range(("r1"))));
deleter.delete();
this.checkRemaining(c, "test", 0);
// test deleting just one row
BatchWriter writer = c.createBatchWriter("test", new BatchWriterConfig());
Mutation m = new Mutation("r1");
m.put("fam", "qual", "value");
writer.addMutation(m);
// make sure the write goes through
writer.flush();
writer.close();
deleter.setRanges(Collections.singletonList(new Range(("r1"))));
deleter.delete();
this.checkRemaining(c, "test", 0);
// test multi row deletes
writer = c.createBatchWriter("test", new BatchWriterConfig());
m = new Mutation("r1");
m.put("fam", "qual", "value");
writer.addMutation(m);
Mutation m2 = new Mutation("r2");
m2.put("fam", "qual", "value");
writer.addMutation(m2);
// make sure the write goes through
writer.flush();
writer.close();
deleter.setRanges(Collections.singletonList(new Range(("r1"))));
deleter.delete();
checkRemaining(c, "test", 1);
}
/**
* Test to make sure that a certain number of rows remain
*
* @param c
* connector to the {@link MockInstance}
* @param tableName
* Table to check
* @param count
* number of entries to expect in the table
*/
private void checkRemaining(Connector c, String tableName, int count) throws Exception {
Scanner scanner = c.createScanner(tableName, Authorizations.EMPTY);
int total = Iterators.size(scanner.iterator());
assertEquals(count, total);
}
@Test
public void testCMod() throws Exception {
// test writing to a table that the is being scanned
Connector c = new MockConnector("root", new MockInstance());
c.tableOperations().create("test");
BatchWriter bw = c.createBatchWriter("test", new BatchWriterConfig());
for (int i = 0; i < 10; i++) {
Mutation m1 = new Mutation("r" + i);
m1.put("cf1", "cq1", 1, "v" + i);
bw.addMutation(m1);
}
bw.flush();
int count = 10;
Scanner scanner = c.createScanner("test", Authorizations.EMPTY);
for (Entry<Key,Value> entry : scanner) {
Key key = entry.getKey();
Mutation m = new Mutation(key.getRow());
m.put(key.getColumnFamily().toString(), key.getColumnQualifier().toString(), key.getTimestamp() + 1, "v" + (count));
count++;
bw.addMutation(m);
}
bw.flush();
count = 10;
for (Entry<Key,Value> entry : scanner) {
assertEquals(entry.getValue().toString(), "v" + (count++));
}
assertEquals(count, 20);
try {
c.tableOperations().create("test_this_$tableName");
assertTrue(false);
} catch (IllegalArgumentException iae) {
}
}
private void checkEntry(Entry<Key,Value> next, String row, String cf, String cq, String value) {
assertEquals(row, next.getKey().getRow().toString());
assertEquals(cf, next.getKey().getColumnFamily().toString());
assertEquals(cq, next.getKey().getColumnQualifier().toString());
assertEquals(value, next.getValue().toString());
}
@Test
public void testMockMultiTableBatchWriter() throws Exception {
Connector c = new MockConnector("root", new MockInstance());
c.tableOperations().create("a");
c.tableOperations().create("b");
MultiTableBatchWriter bw = c.createMultiTableBatchWriter(new BatchWriterConfig());
Mutation m1 = new Mutation("r1");
m1.put("cf1", "cq1", 1, "v1");
BatchWriter b = bw.getBatchWriter("a");
b.addMutation(m1);
b.flush();
b = bw.getBatchWriter("b");
b.addMutation(m1);
b.flush();
Scanner scanner = c.createScanner("a", Authorizations.EMPTY);
int count = Iterators.size(scanner.iterator());
assertEquals(1, count);
scanner = c.createScanner("b", Authorizations.EMPTY);
count = Iterators.size(scanner.iterator());
assertEquals(1, count);
}
@Test
public void testUpdate() throws Exception {
Connector c = new MockConnector("root", new MockInstance());
c.tableOperations().create("test");
BatchWriter bw = c.createBatchWriter("test", new BatchWriterConfig());
for (int i = 0; i < 10; i++) {
Mutation m = new Mutation("r1");
m.put("cf1", "cq1", "" + i);
bw.addMutation(m);
}
bw.close();
Scanner scanner = c.createScanner("test", Authorizations.EMPTY);
Entry<Key,Value> entry = scanner.iterator().next();
assertEquals("9", entry.getValue().toString());
}
@Test
public void testMockConnectorReturnsCorrectInstance() throws AccumuloException, AccumuloSecurityException {
String name = "an-interesting-instance-name";
Instance mockInstance = new MockInstance(name);
assertEquals(mockInstance, mockInstance.getConnector("foo", new PasswordToken("bar")).getInstance());
assertEquals(name, mockInstance.getConnector("foo", new PasswordToken("bar")).getInstance().getInstanceName());
}
}