/**
* 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 org.apache.aurora.scheduler.storage.log;
import java.util.Set;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableSet;
import org.apache.aurora.common.testing.easymock.EasyMockTest;
import org.apache.aurora.gen.Attribute;
import org.apache.aurora.gen.HostAttributes;
import org.apache.aurora.gen.JobUpdateKey;
import org.apache.aurora.gen.MaintenanceMode;
import org.apache.aurora.gen.storage.Op;
import org.apache.aurora.gen.storage.PruneJobUpdateHistory;
import org.apache.aurora.gen.storage.SaveHostAttributes;
import org.apache.aurora.gen.storage.SaveTasks;
import org.apache.aurora.scheduler.base.JobKeys;
import org.apache.aurora.scheduler.base.TaskTestUtil;
import org.apache.aurora.scheduler.events.EventSink;
import org.apache.aurora.scheduler.events.PubsubEvent;
import org.apache.aurora.scheduler.storage.AttributeStore;
import org.apache.aurora.scheduler.storage.CronJobStore;
import org.apache.aurora.scheduler.storage.JobUpdateStore;
import org.apache.aurora.scheduler.storage.LockStore;
import org.apache.aurora.scheduler.storage.QuotaStore;
import org.apache.aurora.scheduler.storage.SchedulerStore;
import org.apache.aurora.scheduler.storage.TaskStore;
import org.apache.aurora.scheduler.storage.entities.IHostAttributes;
import org.apache.aurora.scheduler.storage.entities.IJobUpdateKey;
import org.apache.aurora.scheduler.storage.entities.IScheduledTask;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.LoggerFactory;
import static org.easymock.EasyMock.expect;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class WriteAheadStorageTest extends EasyMockTest {
private LogStorage.TransactionManager transactionManager;
private TaskStore.Mutable taskStore;
private AttributeStore.Mutable attributeStore;
private JobUpdateStore.Mutable jobUpdateStore;
private EventSink eventSink;
private WriteAheadStorage storage;
@Before
public void setUp() {
transactionManager = createMock(LogStorage.TransactionManager.class);
taskStore = createMock(TaskStore.Mutable.class);
attributeStore = createMock(AttributeStore.Mutable.class);
jobUpdateStore = createMock(JobUpdateStore.Mutable.class);
eventSink = createMock(EventSink.class);
storage = new WriteAheadStorage(
transactionManager,
createMock(SchedulerStore.Mutable.class),
createMock(CronJobStore.Mutable.class),
taskStore,
createMock(LockStore.Mutable.class),
createMock(QuotaStore.Mutable.class),
attributeStore,
jobUpdateStore,
LoggerFactory.getLogger(WriteAheadStorageTest.class),
eventSink);
}
private void expectOp(Op op) {
expect(transactionManager.hasActiveTransaction()).andReturn(true);
transactionManager.log(op);
}
@Test
public void testPruneHistory() {
Set<IJobUpdateKey> pruned = ImmutableSet.of(
IJobUpdateKey.build(new JobUpdateKey(JobKeys.from("role", "env", "job").newBuilder(), "a")),
IJobUpdateKey.build(
new JobUpdateKey(JobKeys.from("role", "env", "job").newBuilder(), "b")));
expect(jobUpdateStore.pruneHistory(1, 1)).andReturn(pruned);
expectOp(Op.pruneJobUpdateHistory(new PruneJobUpdateHistory(1, 1)));
control.replay();
storage.pruneHistory(1, 1);
}
@Test
public void testNoopPruneHistory() {
expect(jobUpdateStore.pruneHistory(1, 1)).andReturn(ImmutableSet.of());
control.replay();
storage.pruneHistory(1, 1);
}
@Test
public void testMutate() {
String taskId = "a";
Function<IScheduledTask, IScheduledTask> mutator =
createMock(new Clazz<Function<IScheduledTask, IScheduledTask>>() { });
Optional<IScheduledTask> mutated = Optional.of(TaskTestUtil.makeTask(taskId, TaskTestUtil.JOB));
expect(taskStore.mutateTask(taskId, mutator)).andReturn(mutated);
expectOp(Op.saveTasks(new SaveTasks(ImmutableSet.of(mutated.get().newBuilder()))));
control.replay();
assertEquals(mutated, storage.mutateTask(taskId, mutator));
}
@Test
public void testSaveHostAttributes() {
IHostAttributes attributes = IHostAttributes.build(
new HostAttributes()
.setHost("a")
.setMode(MaintenanceMode.DRAINING)
.setAttributes(ImmutableSet.of(
new Attribute().setName("b").setValues(ImmutableSet.of("1", "2")))));
expect(attributeStore.saveHostAttributes(attributes)).andReturn(true);
expectOp(Op.saveHostAttributes(
new SaveHostAttributes().setHostAttributes(attributes.newBuilder())));
eventSink.post(new PubsubEvent.HostAttributesChanged(attributes));
expect(attributeStore.saveHostAttributes(attributes)).andReturn(false);
control.replay();
assertTrue(storage.saveHostAttributes(attributes));
assertFalse(storage.saveHostAttributes(attributes));
}
@Test(expected = UnsupportedOperationException.class)
public void testDeleteAllTasks() {
control.replay();
storage.deleteAllTasks();
}
@Test(expected = UnsupportedOperationException.class)
public void testDeleteHostAttributes() {
control.replay();
storage.deleteHostAttributes();
}
@Test(expected = UnsupportedOperationException.class)
public void testDeleteJobs() {
control.replay();
storage.deleteJobs();
}
@Test(expected = UnsupportedOperationException.class)
public void testDeleteQuotas() {
control.replay();
storage.deleteQuotas();
}
@Test(expected = UnsupportedOperationException.class)
public void testDeleteLocks() {
control.replay();
storage.deleteLocks();
}
@Test(expected = UnsupportedOperationException.class)
public void testDeleteAllUpdatesAndEvents() {
control.replay();
storage.deleteAllUpdatesAndEvents();
}
}