/* * Copyright (c) 2013, the Dart project authors. * * Licensed under the Eclipse Public License v1.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.eclipse.org/legal/epl-v10.html * * 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.google.dart.ui.test.driver; import com.google.common.collect.Lists; import com.google.dart.tools.internal.corext.refactoring.util.ExecutionUtils; import com.google.dart.ui.test.util.UiContext; import org.eclipse.swt.widgets.Display; import java.util.LinkedList; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; /** * Executes a sequence of {@link Operation}s. */ public class OperationExecutor { private final Display display = Display.getDefault(); private final UiContext context = new UiContext(); private final LinkedList<Operation> operations = Lists.newLinkedList(); private final AtomicBoolean operationsDone = new AtomicBoolean(); private Throwable exception = null; /** * Schedules the {@link Operation} for execution. */ public void addOperation(Operation operation) { operations.add(operation); } /** * Runs the scheduled {@link Operation}s, waits for the given time at most. */ public void runUiOperations(long waitFor, TimeUnit unit) throws Exception { display.timerExec(5, new Runnable() { private LinkedList<Operation> finishOperations = Lists.newLinkedList(); @Override public void run() { // are we done? if (operationsDone.get()) { return; } // schedule again display.timerExec(5, this); // run single operation try { // wait for current operation done if (!finishOperations.isEmpty()) { Operation operation = finishOperations.getFirst(); if (operation.isDone(context)) { finishOperations.removeFirst(); operation.done(context); maybeDone(); } return; } // prepare new operation if (operations.isEmpty()) { return; } Operation operation = operations.getFirst(); // wait for new operation ready if (operation.isReady(context)) { operations.removeFirst(); try { operation.run(context); // done operation if (operation.isDone(context)) { operation.done(context); } else { finishOperations.addLast(operation); } // may be done execution maybeDone(); } catch (Throwable e) { operation.onError(context); ExecutionUtils.propagate(e); } } } catch (Throwable e) { if (exception == null) { exception = e; } // we are done - with failure operationsDone.set(true); } } private void maybeDone() { if (operations.isEmpty() && finishOperations.isEmpty()) { operationsDone.set(true); } } }); // wait for successful completion or failure { long end = System.nanoTime() + unit.toNanos(waitFor); while (!operationsDone.get()) { if (System.nanoTime() >= end) { throw new TimeoutException(); } UiContext.runEventLoop(10); } } // check for exception if (exception != null) { ExecutionUtils.propagate(exception); } // OK } }