blob: 38068f1c9737b6256552b2a8b1525af2e7375feb [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 SF 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.sling.hc.it.core;
import static org.junit.Assert.assertTrue;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import javax.inject.Inject;
import org.apache.sling.hc.api.HealthCheck;
import org.apache.sling.hc.api.Result;
import org.apache.sling.hc.api.execution.HealthCheckExecutionResult;
import org.apache.sling.hc.api.execution.HealthCheckExecutor;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.PaxExam;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
@RunWith(PaxExam.class)
public class AsyncHealthCheckTest {
@Inject
private HealthCheckExecutor executor;
@Inject
private BundleContext bundleContext;
@Configuration
public Option[] config() {
return U.config();
}
@Test
public void testAsyncHealthCheck() throws InterruptedException {
final String id = UUID.randomUUID().toString();
final AtomicInteger counter = new AtomicInteger(Integer.MIN_VALUE);
final HealthCheck hc = new HealthCheck() {
@Override
public Result execute() {
final int v = counter.incrementAndGet();
return new Result(Result.Status.OK, "counter is now " + v);
}
};
final Dictionary<String, Object> props = new Hashtable<String, Object>();
props.put(HealthCheck.NAME, "name_" + id);
props.put(HealthCheck.TAGS, id);
props.put(HealthCheck.ASYNC_CRON_EXPRESSION, "*/1 * * * * ?");
@SuppressWarnings("rawtypes")
final ServiceRegistration reg = bundleContext.registerService(HealthCheck.class, hc, props);
try {
{
// Wait for HC to be registered
final long timeout = System.currentTimeMillis() + 10000L;
boolean hcFound = false;
while(System.currentTimeMillis() < timeout) {
final List<HealthCheckExecutionResult> results = executor.execute(id);
if(!results.isEmpty()) {
hcFound = true;
break;
}
Thread.sleep(100L);
}
assertTrue("Expecting HC to become active", hcFound);
}
// Now reset the counter and check that HC increments it even if we don't
// use the executor
{
counter.set(0);
final long timeout = System.currentTimeMillis() + 5000L;
while(System.currentTimeMillis() < timeout) {
if(counter.get() > 0) {
break;
}
Thread.sleep(100L);
}
assertTrue("Expecting counter to be incremented", counter.get() > 0);
}
// Verify that we get the right log
final String msg = executor.execute(id).get(0).getHealthCheckResult().iterator().next().getMessage();
assertTrue("Expecting the right message: " + msg, msg.contains("counter is now"));
// And verify that calling executor lots of times doesn't increment as much
final int previous = counter.get();
final int n = 100;
for(int i=0; i < n; i++) {
executor.execute(id);
}
assertTrue("Expecting counter to increment asynchronously", counter.get() < previous + n);
} finally {
reg.unregister();
}
}
}