You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aurora.apache.org by wf...@apache.org on 2014/10/31 22:00:52 UTC
git commit: Add stat gauge coverage for AsyncModule and MemStorage.
Repository: incubator-aurora
Updated Branches:
refs/heads/master 02a1c040e -> 765f2dd4e
Add stat gauge coverage for AsyncModule and MemStorage.
Bugs closed: AURORA-884
Reviewed at https://reviews.apache.org/r/27371/
Project: http://git-wip-us.apache.org/repos/asf/incubator-aurora/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-aurora/commit/765f2dd4
Tree: http://git-wip-us.apache.org/repos/asf/incubator-aurora/tree/765f2dd4
Diff: http://git-wip-us.apache.org/repos/asf/incubator-aurora/diff/765f2dd4
Branch: refs/heads/master
Commit: 765f2dd4e4392bc8ce33bc823329b95a6f26924c
Parents: 02a1c04
Author: Bill Farner <wf...@apache.org>
Authored: Fri Oct 31 14:00:39 2014 -0700
Committer: Bill Farner <wf...@apache.org>
Committed: Fri Oct 31 14:00:39 2014 -0700
----------------------------------------------------------------------
.../apache/aurora/CoverageReportCheck.groovy | 17 ++-
config/legacy_untested_classes.txt | 14 ---
.../aurora/scheduler/async/AsyncModule.java | 99 +++++++++++----
.../scheduler/storage/mem/MemStorage.java | 49 ++++++--
.../aurora/scheduler/async/AsyncModuleTest.java | 123 +++++++++++++++++++
.../scheduler/storage/mem/MemStorageTest.java | 14 ++-
.../scheduler/testing/FakeStatsProvider.java | 18 +++
.../aurora/scheduler/updater/JobUpdaterIT.java | 3 +
8 files changed, 283 insertions(+), 54 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/765f2dd4/buildSrc/src/main/groovy/org/apache/aurora/CoverageReportCheck.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/aurora/CoverageReportCheck.groovy b/buildSrc/src/main/groovy/org/apache/aurora/CoverageReportCheck.groovy
index 06d25c0..1d98442 100644
--- a/buildSrc/src/main/groovy/org/apache/aurora/CoverageReportCheck.groovy
+++ b/buildSrc/src/main/groovy/org/apache/aurora/CoverageReportCheck.groovy
@@ -78,9 +78,22 @@ class CoverageReportCheck extends DefaultTask {
// constructor for anonymous classes. Anonymous classes are identified by their name,
// which we expect to be of the form 'Something$1'. Jacoco names default constructors
// '<init>', so we filter based on that.
- def methodFilter = cls.@name ==~ /.*\$\d+/ ? { m -> m.@name != '<init>' } : { true }
+ def isAnonymous = { c -> c.@name ==~ /.*\$\d+/ }
+ def methodFilter = isAnonymous(cls) ? { m -> m.@name != '<init>' } : { true }
+
+ def matchedMethods = cls.method.findAll(methodFilter)
+ if (isAnonymous(cls) && matchedMethods.isEmpty()) {
+ // Ignore anonymous classes that only have a constructor. This will avoid tripping for
+ // things like TypeLiteral and Clazz.
+ if (cls.@name in legacyClassesWithoutCoverage) {
+ return 'Please remove ' + cls.@name + ' from the legacyClassesWithoutCoverage list' \
+ + ', this check does not apply for constructor-only anonymous classes.'
+ } else {
+ return null
+ }
+ }
- def covered = cls.method.findAll(methodFilter).collect { m ->
+ def covered = matchedMethods.collect { m ->
m.counter.find({ c -> c.@type == 'INSTRUCTION' }).@covered.toInteger()}.sum(0)
if (cls.@name in legacyClassesWithoutCoverage) {
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/765f2dd4/config/legacy_untested_classes.txt
----------------------------------------------------------------------
diff --git a/config/legacy_untested_classes.txt b/config/legacy_untested_classes.txt
index 542ac31..f1d1921 100644
--- a/config/legacy_untested_classes.txt
+++ b/config/legacy_untested_classes.txt
@@ -5,10 +5,6 @@ org/apache/aurora/auth/UnsecureAuthModule$UnsecureSessionValidator$1
org/apache/aurora/Protobufs$1
org/apache/aurora/scheduler/app/SchedulerMain$2
org/apache/aurora/scheduler/app/SchedulerMain$3
-org/apache/aurora/scheduler/async/AsyncModule$1
-org/apache/aurora/scheduler/async/AsyncModule$10$1
-org/apache/aurora/scheduler/async/AsyncModule$3$1
-org/apache/aurora/scheduler/async/AsyncModule$4$1
org/apache/aurora/scheduler/async/GcExecutorLauncher$1
org/apache/aurora/scheduler/async/OfferQueue$OfferQueueImpl$2
org/apache/aurora/scheduler/base/Conversions$1
@@ -18,7 +14,6 @@ org/apache/aurora/scheduler/base/Conversions$4
org/apache/aurora/scheduler/cron/quartz/CronSchedulerImpl
org/apache/aurora/scheduler/cron/quartz/CronSchedulerImpl$1
org/apache/aurora/scheduler/http/JerseyTemplateServlet
-org/apache/aurora/scheduler/http/JettyServerModule$1
org/apache/aurora/scheduler/http/Maintenance
org/apache/aurora/scheduler/http/Maintenance$1
org/apache/aurora/scheduler/http/Maintenance$2
@@ -55,22 +50,13 @@ org/apache/aurora/scheduler/http/Utilization$Display
org/apache/aurora/scheduler/http/Utilization$DisplayMetric
org/apache/aurora/scheduler/log/Log$Stream$InvalidPositionException
org/apache/aurora/scheduler/log/mesos/MesosLogStreamModule
-org/apache/aurora/scheduler/log/mesos/MesosLogStreamModule$1
-org/apache/aurora/scheduler/log/mesos/MesosLogStreamModule$2
org/apache/aurora/scheduler/log/mesos/MesosLogStreamModule$3
org/apache/aurora/scheduler/log/mesos/MesosLogStreamModule$4
org/apache/aurora/scheduler/log/mesos/MesosLogStreamModule$5
org/apache/aurora/scheduler/state/MaintenanceController$MaintenanceControllerImpl$4
org/apache/aurora/scheduler/state/MaintenanceController$MaintenanceControllerImpl$8
org/apache/aurora/scheduler/stats/AsyncStatsModule$OfferAdapter$1
-org/apache/aurora/scheduler/storage/backup/BackupModule$1
-org/apache/aurora/scheduler/storage/backup/BackupModule$2
org/apache/aurora/scheduler/storage/log/LogStorage$RecoveryFailedException
-org/apache/aurora/scheduler/storage/log/LogStorageModule$1
-org/apache/aurora/scheduler/storage/log/LogStorageModule$2
org/apache/aurora/scheduler/storage/mem/Util
org/apache/aurora/scheduler/storage/mem/Util$1
-org/apache/aurora/scheduler/thrift/aop/AopModule$2$1
-org/apache/aurora/scheduler/thrift/aop/AopModule$2$2
-org/apache/aurora/scheduler/thrift/auth/ThriftAuthModule$1
org/apache/aurora/scheduler/updater/UpdateConfigurationException
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/765f2dd4/src/main/java/org/apache/aurora/scheduler/async/AsyncModule.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/async/AsyncModule.java b/src/main/java/org/apache/aurora/scheduler/async/AsyncModule.java
index 90b26e5..df7e56a 100644
--- a/src/main/java/org/apache/aurora/scheduler/async/AsyncModule.java
+++ b/src/main/java/org/apache/aurora/scheduler/async/AsyncModule.java
@@ -20,27 +20,27 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.logging.Logger;
+import javax.inject.Inject;
import javax.inject.Qualifier;
import javax.inject.Singleton;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
+import com.google.common.base.Supplier;
import com.google.common.util.concurrent.RateLimiter;
import com.google.inject.AbstractModule;
import com.google.inject.Binder;
import com.google.inject.Key;
import com.google.inject.PrivateModule;
import com.google.inject.TypeLiteral;
-
import com.twitter.common.application.modules.LifecycleModule;
import com.twitter.common.args.Arg;
import com.twitter.common.args.CmdLine;
import com.twitter.common.args.constraints.NotNegative;
import com.twitter.common.args.constraints.Positive;
+import com.twitter.common.base.Command;
import com.twitter.common.quantity.Amount;
import com.twitter.common.quantity.Time;
-import com.twitter.common.stats.StatImpl;
-import com.twitter.common.stats.Stats;
import com.twitter.common.stats.StatsProvider;
import com.twitter.common.util.Random;
import com.twitter.common.util.TruncatedBinaryBackoff;
@@ -61,6 +61,7 @@ import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static java.util.Objects.requireNonNull;
import static org.apache.aurora.scheduler.async.Preemptor.PreemptorImpl;
import static org.apache.aurora.scheduler.async.Preemptor.PreemptorImpl.PreemptionDelay;
@@ -203,19 +204,34 @@ public class AsyncModule extends AbstractModule {
@CmdLine(name = "gc_executor_path", help = "Path to the gc executor launch script.")
private static final Arg<String> GC_EXECUTOR_PATH = Arg.create(null);
+ @Qualifier
+ @Target({ FIELD, PARAMETER, METHOD }) @Retention(RUNTIME)
+ private @interface AsyncExecutor { }
+
+ private final boolean enablePreemptor;
+
+ @VisibleForTesting
+ AsyncModule(boolean enablePreemptor) {
+ this.enablePreemptor = enablePreemptor;
+ }
+
+ public AsyncModule() {
+ this(ENABLE_PREEMPTOR.get());
+ }
+
+ @VisibleForTesting
+ static final String TIMEOUT_QUEUE_GAUGE = "timeout_queue_size";
+
+ @VisibleForTesting
+ static final String ASYNC_TASKS_GAUGE = "async_tasks_completed";
+
@Override
protected void configure() {
// Don't worry about clean shutdown, these can be daemon and cleanup-free.
final ScheduledThreadPoolExecutor executor =
AsyncUtil.loggingScheduledExecutor(ASYNC_WORKER_THREADS.get(), "AsyncProcessor-%d", LOG);
-
- Stats.exportSize("timeout_queue_size", executor.getQueue());
- Stats.export(new StatImpl<Long>("async_tasks_completed") {
- @Override
- public Long read() {
- return executor.getCompletedTaskCount();
- }
- });
+ bind(ScheduledThreadPoolExecutor.class).annotatedWith(AsyncExecutor.class).toInstance(executor);
+ LifecycleModule.bindStartupAction(binder(), RegisterGauges.class);
// AsyncModule itself is not a subclass of PrivateModule because TaskEventModule internally uses
// a MultiBinder, which cannot span multiple injectors.
@@ -227,7 +243,6 @@ public class AsyncModule extends AbstractModule {
bind(ScheduledExecutorService.class).toInstance(executor);
bind(TaskTimeout.class).in(Singleton.class);
- requireBinding(StatsProvider.class);
expose(TaskTimeout.class);
}
});
@@ -251,7 +266,7 @@ public class AsyncModule extends AbstractModule {
bind(RescheduleCalculator.class).to(RescheduleCalculatorImpl.class).in(Singleton.class);
expose(RescheduleCalculator.class);
- if (ENABLE_PREEMPTOR.get()) {
+ if (enablePreemptor) {
bind(PREEMPTOR_KEY).to(PreemptorImpl.class);
bind(PreemptorImpl.class).in(Singleton.class);
LOG.info("Preemptor Enabled.");
@@ -356,17 +371,53 @@ public class AsyncModule extends AbstractModule {
Binder binder,
final Key<Preemptor> preemptorKey,
final Amount<Long, Time> reservationDuration) {
- binder.install(new PrivateModule() {
- @Override
- protected void configure() {
- bind(Preemptor.class).to(preemptorKey);
- bind(new TypeLiteral<Amount<Long, Time>>() { }).annotatedWith(ReservationDuration.class)
- .toInstance(reservationDuration);
- bind(TaskScheduler.class).to(TaskSchedulerImpl.class);
- bind(TaskSchedulerImpl.class).in(Singleton.class);
- expose(TaskScheduler.class);
+
+ binder.install(new PrivateModule() {
+ @Override
+ protected void configure() {
+ bind(Preemptor.class).to(preemptorKey);
+ bind(new TypeLiteral<Amount<Long, Time>>() { }).annotatedWith(ReservationDuration.class)
+ .toInstance(reservationDuration);
+ bind(TaskScheduler.class).to(TaskSchedulerImpl.class);
+ bind(TaskSchedulerImpl.class).in(Singleton.class);
+ expose(TaskScheduler.class);
+ }
+ });
+ PubsubEventModule.bindSubscriber(binder, TaskScheduler.class);
+ }
+
+ static class RegisterGauges implements Command {
+ private final StatsProvider statsProvider;
+ private final ScheduledThreadPoolExecutor executor;
+
+ @Inject
+ RegisterGauges(
+ StatsProvider statsProvider,
+ @AsyncExecutor ScheduledThreadPoolExecutor executor) {
+
+ this.statsProvider = requireNonNull(statsProvider);
+ this.executor = requireNonNull(executor);
+ }
+
+ @Override
+ public void execute() throws RuntimeException {
+ statsProvider.makeGauge(
+ TIMEOUT_QUEUE_GAUGE,
+ new Supplier<Integer>() {
+ @Override
+ public Integer get() {
+ return executor.getQueue().size();
+ }
+ });
+ statsProvider.makeGauge(
+ ASYNC_TASKS_GAUGE,
+ new Supplier<Long>() {
+ @Override
+ public Long get() {
+ return executor.getCompletedTaskCount();
+ }
}
- });
- PubsubEventModule.bindSubscriber(binder, TaskScheduler.class);
+ );
+ }
}
}
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/765f2dd4/src/main/java/org/apache/aurora/scheduler/storage/mem/MemStorage.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/storage/mem/MemStorage.java b/src/main/java/org/apache/aurora/scheduler/storage/mem/MemStorage.java
index 31498fa..2cc76dc 100644
--- a/src/main/java/org/apache/aurora/scheduler/storage/mem/MemStorage.java
+++ b/src/main/java/org/apache/aurora/scheduler/storage/mem/MemStorage.java
@@ -23,14 +23,16 @@ import javax.inject.Inject;
import javax.inject.Qualifier;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Supplier;
+import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.twitter.common.inject.Bindings;
import com.twitter.common.inject.TimedInterceptor.Timed;
import com.twitter.common.stats.SlidingStats;
-import com.twitter.common.stats.StatImpl;
import com.twitter.common.stats.Stats;
+import com.twitter.common.stats.StatsProvider;
import org.apache.aurora.scheduler.storage.AttributeStore;
import org.apache.aurora.scheduler.storage.JobStore;
@@ -79,6 +81,9 @@ public class MemStorage implements Storage {
@Qualifier
public @interface Delegated { }
+ @VisibleForTesting
+ static final String THREADS_WAITING_GAUGE = "storage_lock_threads_waiting";
+
@Inject
MemStorage(
@Delegated final SchedulerStore.Mutable schedulerStore,
@@ -88,9 +93,10 @@ public class MemStorage implements Storage {
@Delegated final Storage delegated,
@Delegated final QuotaStore.Mutable quotaStore,
@Delegated final AttributeStore.Mutable attributeStore,
- @Delegated final JobUpdateStore.Mutable updateStore) {
+ @Delegated final JobUpdateStore.Mutable updateStore,
+ StatsProvider statsProvider) {
- this.delegatedStore = delegated;
+ this.delegatedStore = requireNonNull(delegated);
storeProvider = new MutableStoreProvider() {
@Override
public SchedulerStore.Mutable getSchedulerStore() {
@@ -133,28 +139,47 @@ public class MemStorage implements Storage {
}
};
- Stats.export(new StatImpl<Integer>("storage_lock_threads_waiting") {
- @Override
- public Integer read() {
- return lockManager.getQueueLength();
- }
- });
+ statsProvider.makeGauge(
+ THREADS_WAITING_GAUGE,
+ new Supplier<Integer>() {
+ @Override
+ public Integer get() {
+ return lockManager.getQueueLength();
+ }
+ }
+ );
}
/**
- * Creates a new empty in-memory storage for use in testing.
+ * Creates a new empty in-memory storage for use in testing, exporting gauges to the provided
+ * stats provider. NOTE: Due to the fact that some libraries statically access {@link Stats},
+ * not all guaranteed to use the stats provider.
*/
@VisibleForTesting
- public static Storage newEmptyStorage() {
+ public static Storage newEmptyStorage(final StatsProvider statsProvider) {
Injector injector = Guice.createInjector(
DbModule.testModule(Bindings.annotatedKeyFactory(Delegated.class)),
- new MemStorageModule(Bindings.annotatedKeyFactory(Volatile.class)));
+ new MemStorageModule(Bindings.annotatedKeyFactory(Volatile.class)),
+ new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(StatsProvider.class).toInstance(statsProvider);
+ }
+ });
Storage storage = injector.getInstance(Key.get(Storage.class, Volatile.class));
storage.prepare();
return storage;
}
+ /**
+ * Creates a new empty in-memory storage for use in testing.
+ */
+ @VisibleForTesting
+ public static Storage newEmptyStorage() {
+ return newEmptyStorage(Stats.STATS_PROVIDER);
+ }
+
private <S extends StoreProvider, T, E extends Exception> T doWork(
LockType lockType,
S stores,
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/765f2dd4/src/test/java/org/apache/aurora/scheduler/async/AsyncModuleTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/async/AsyncModuleTest.java b/src/test/java/org/apache/aurora/scheduler/async/AsyncModuleTest.java
new file mode 100644
index 0000000..62d8aab
--- /dev/null
+++ b/src/test/java/org/apache/aurora/scheduler/async/AsyncModuleTest.java
@@ -0,0 +1,123 @@
+/**
+ * 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.async;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.twitter.common.application.StartupStage;
+import com.twitter.common.application.modules.LifecycleModule;
+import com.twitter.common.base.ExceptionalCommand;
+import com.twitter.common.stats.StatsProvider;
+import com.twitter.common.testing.easymock.EasyMockTest;
+import com.twitter.common.util.Clock;
+
+import org.apache.aurora.scheduler.Driver;
+import org.apache.aurora.scheduler.filter.AttributeAggregate;
+import org.apache.aurora.scheduler.filter.SchedulingFilter;
+import org.apache.aurora.scheduler.state.MaintenanceController;
+import org.apache.aurora.scheduler.state.StateManager;
+import org.apache.aurora.scheduler.state.TaskAssigner;
+import org.apache.aurora.scheduler.storage.AttributeStore;
+import org.apache.aurora.scheduler.storage.Storage;
+import org.apache.aurora.scheduler.storage.entities.IScheduledTask;
+import org.apache.aurora.scheduler.storage.testing.StorageTestUtil;
+import org.apache.aurora.scheduler.testing.FakeStatsProvider;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * TODO(wfarner): Make this test more useful by validating the bindings set up by the module.
+ * Multibindings makes this tricky since it uses an internal binding annotation which makes a direct
+ * check on injector.getBindings() impossible.
+ */
+public class AsyncModuleTest extends EasyMockTest {
+
+ private FakeStatsProvider statsProvider;
+ private StorageTestUtil storageUtil;
+
+ @Before
+ public void setUp() {
+ statsProvider = new FakeStatsProvider();
+ storageUtil = new StorageTestUtil(this);
+ storageUtil.expectOperations();
+ }
+
+ private Injector createInjector(Module module) {
+ return Guice.createInjector(
+ module,
+ new LifecycleModule(),
+ new AbstractModule() {
+ private <T> void bindMock(Class<T> clazz) {
+ bind(clazz).toInstance(createMock(clazz));
+ }
+
+ @Override
+ protected void configure() {
+ bind(StatsProvider.class).toInstance(statsProvider);
+ bindMock(Clock.class);
+ bindMock(Driver.class);
+ bindMock(SchedulingFilter.class);
+ bindMock(MaintenanceController.class);
+ bindMock(StateManager.class);
+ bindMock(TaskAssigner.class);
+ bindMock(Thread.UncaughtExceptionHandler.class);
+ bind(Storage.class).toInstance(storageUtil.storage);
+ }
+ });
+ }
+
+ @Test
+ public void testBindings() throws Exception {
+ Injector injector = createInjector(new AsyncModule(true));
+
+ control.replay();
+
+ injector.getInstance(Key.get(ExceptionalCommand.class, StartupStage.class)).execute();
+
+ injector.getBindings();
+
+ assertEquals(
+ ImmutableMap.of(AsyncModule.TIMEOUT_QUEUE_GAUGE, 0, AsyncModule.ASYNC_TASKS_GAUGE, 0L),
+ statsProvider.getAllValues()
+ );
+ }
+
+ @Test
+ public void testPreemptorDisabled() throws Exception {
+ Injector injector = createInjector(new AsyncModule(false));
+
+ Supplier<ImmutableSet<IScheduledTask>> taskSupplier =
+ createMock(new Clazz<Supplier<ImmutableSet<IScheduledTask>>>() { });
+ AttributeStore attributeStore = createMock(AttributeStore.class);
+
+ control.replay();
+
+ injector.getInstance(Key.get(ExceptionalCommand.class, StartupStage.class)).execute();
+
+ injector.getBindings();
+ assertEquals(
+ Optional.<String>absent(),
+ injector.getInstance(AsyncModule.PREEMPTOR_KEY)
+ .findPreemptionSlotFor("a", new AttributeAggregate(taskSupplier, attributeStore)));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/765f2dd4/src/test/java/org/apache/aurora/scheduler/storage/mem/MemStorageTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/storage/mem/MemStorageTest.java b/src/test/java/org/apache/aurora/scheduler/storage/mem/MemStorageTest.java
index abf6868..463b445 100644
--- a/src/test/java/org/apache/aurora/scheduler/storage/mem/MemStorageTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/storage/mem/MemStorageTest.java
@@ -45,6 +45,7 @@ import org.apache.aurora.scheduler.storage.Storage.StoreProvider;
import org.apache.aurora.scheduler.storage.Storage.Work;
import org.apache.aurora.scheduler.storage.entities.IResourceAggregate;
import org.apache.aurora.scheduler.storage.entities.IScheduledTask;
+import org.apache.aurora.scheduler.testing.FakeStatsProvider;
import org.junit.Before;
import org.junit.Test;
@@ -57,11 +58,12 @@ import static org.junit.Assert.fail;
public class MemStorageTest extends TearDownTestCase {
private ExecutorService executor;
+ private FakeStatsProvider statsProvider;
private Storage storage;
@Before
public void setUp() {
- executor = Executors.newSingleThreadExecutor(
+ executor = Executors.newCachedThreadPool(
new ThreadFactoryBuilder().setNameFormat("SlowRead-%d").setDaemon(true).build());
addTearDown(new TearDown() {
@Override
@@ -69,7 +71,8 @@ public class MemStorageTest extends TearDownTestCase {
new ExecutorServiceShutdown(executor, Amount.of(1L, Time.SECONDS)).execute();
}
});
- storage = MemStorage.newEmptyStorage();
+ statsProvider = new FakeStatsProvider();
+ storage = MemStorage.newEmptyStorage(statsProvider);
}
@Test
@@ -108,6 +111,13 @@ public class MemStorageTest extends TearDownTestCase {
assertEquals("fastResult", fastResult);
slowReadFinished.countDown();
assertEquals("slowResult", future.get());
+
+ // It would be nice to check the stat values (specifically with simulated lock contention, but
+ // this value is based off ReentrantReadWriteLock#getQueueLength(), which is documented as an
+ // approximation and not a guaranteed accurate value.
+ assertEquals(
+ ImmutableSet.of(MemStorage.THREADS_WAITING_GAUGE),
+ statsProvider.getAllValues().keySet());
}
private IScheduledTask makeTask(String taskId) {
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/765f2dd4/src/test/java/org/apache/aurora/scheduler/testing/FakeStatsProvider.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/testing/FakeStatsProvider.java b/src/test/java/org/apache/aurora/scheduler/testing/FakeStatsProvider.java
index 273129e..768e784 100644
--- a/src/test/java/org/apache/aurora/scheduler/testing/FakeStatsProvider.java
+++ b/src/test/java/org/apache/aurora/scheduler/testing/FakeStatsProvider.java
@@ -16,7 +16,9 @@ package org.apache.aurora.scheduler.testing;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
+import com.google.common.base.Function;
import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.twitter.common.stats.Stat;
import com.twitter.common.stats.StatsProvider;
@@ -37,6 +39,22 @@ public class FakeStatsProvider implements StatsProvider {
return stats.get(statName).get();
}
+ /**
+ * Gets the current values of all exported stats.
+ *
+ * @return All exported stat names and their associated values.
+ */
+ public Map<String, ? extends Number> getAllValues() {
+ return ImmutableMap.copyOf(Maps.transformValues(
+ stats,
+ new Function<Supplier<? extends Number>, Number>() {
+ @Override
+ public Number apply(Supplier<? extends Number> supplier) {
+ return supplier.get();
+ }
+ }));
+ }
+
@Override
public AtomicLong makeCounter(String name) {
final AtomicLong counter = new AtomicLong();
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/765f2dd4/src/test/java/org/apache/aurora/scheduler/updater/JobUpdaterIT.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/updater/JobUpdaterIT.java b/src/test/java/org/apache/aurora/scheduler/updater/JobUpdaterIT.java
index 61b6b8e..8baec04 100644
--- a/src/test/java/org/apache/aurora/scheduler/updater/JobUpdaterIT.java
+++ b/src/test/java/org/apache/aurora/scheduler/updater/JobUpdaterIT.java
@@ -37,6 +37,7 @@ import com.twitter.common.inject.Bindings.KeyFactory;
import com.twitter.common.quantity.Amount;
import com.twitter.common.quantity.Time;
import com.twitter.common.stats.Stats;
+import com.twitter.common.stats.StatsProvider;
import com.twitter.common.testing.easymock.EasyMockTest;
import com.twitter.common.util.Clock;
import com.twitter.common.util.TruncatedBinaryBackoff;
@@ -92,6 +93,7 @@ import org.apache.aurora.scheduler.storage.entities.ITaskConfig;
import org.apache.aurora.scheduler.storage.mem.MemStorage.Delegated;
import org.apache.aurora.scheduler.storage.mem.MemStorageModule;
import org.apache.aurora.scheduler.testing.FakeScheduledExecutor;
+import org.apache.aurora.scheduler.testing.FakeStatsProvider;
import org.easymock.EasyMock;
import org.easymock.IExpectationSetters;
import org.junit.After;
@@ -164,6 +166,7 @@ public class JobUpdaterIT extends EasyMockTest {
new AbstractModule() {
@Override
protected void configure() {
+ bind(StatsProvider.class).toInstance(new FakeStatsProvider());
bind(Clock.class).toInstance(clock);
bind(StateManager.class).to(StateManagerImpl.class);
bind(Driver.class).toInstance(driver);