| /* |
| * Copyright (C) 2011 The Android Open Source Project |
| * |
| * 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 com.android.email; |
| |
| import com.android.email.TestUtils.Condition; |
| import com.android.emailcommon.utility.Utility; |
| |
| import java.util.concurrent.atomic.AtomicInteger; |
| |
| import junit.framework.TestCase; |
| |
| public class SingleRunningTaskTest extends TestCase { |
| |
| private static class NormalTask extends SingleRunningTask<Void> { |
| // # of times the task has actually run. |
| public final AtomicInteger mCalledCount = new AtomicInteger(0); |
| |
| // The task will be blocked if true |
| private volatile boolean mBlocked = false; |
| |
| public NormalTask() { |
| super("task"); |
| } |
| |
| public void block() { |
| mBlocked = true; |
| } |
| |
| public void unblock() { |
| mBlocked = false; |
| synchronized (this) { |
| notify(); |
| } |
| } |
| |
| @Override |
| protected void runInternal(Void param) { |
| mCalledCount.incrementAndGet(); |
| while (mBlocked) { |
| synchronized (this) { |
| try { |
| wait(); |
| } catch (InterruptedException ignore) { |
| } |
| } |
| } |
| } |
| } |
| |
| // Always throws exception |
| private static class FailTask extends SingleRunningTask<Void> { |
| public FailTask() { |
| super("task"); |
| } |
| |
| @Override |
| protected void runInternal(Void param) { |
| throw new RuntimeException("Intentional exception"); |
| } |
| } |
| |
| /** |
| * Run 3 tasks sequentially. |
| */ |
| public void testSequential() { |
| final NormalTask e = new NormalTask(); |
| |
| e.run(null); |
| e.run(null); |
| e.run(null); |
| |
| assertEquals(3, e.mCalledCount.get()); |
| } |
| |
| /** |
| * Run 2 tasks in parallel, and then another call. |
| */ |
| public void testParallel() { |
| final NormalTask e = new NormalTask(); |
| |
| // Block the first task |
| e.block(); |
| |
| // The call will be blocked, so run it on another thread. |
| Utility.runAsync(new Runnable() { |
| @Override |
| public void run() { |
| e.run(null); |
| } |
| }); |
| |
| // Wait until the task really starts. |
| TestUtils.waitUntil(new Condition() { |
| @Override |
| public boolean isMet() { |
| return e.mCalledCount.get() >= 1; |
| } |
| }, 10); |
| |
| // Now the task is running, blocked. |
| |
| // This call will just be ignored. |
| e.run(null); |
| |
| assertEquals(1, e.mCalledCount.get()); |
| |
| // Let the thread finish. |
| e.unblock(); |
| |
| // Wait until the task really finishes. |
| TestUtils.waitUntil(new Condition() { |
| @Override |
| public boolean isMet() { |
| return !e.isRunningForTest(); |
| } |
| }, 10); |
| |
| // Now this should not be ignored. |
| e.run(null); |
| |
| assertEquals(2, e.mCalledCount.get()); |
| } |
| |
| /** |
| * If a task throws, isRunning should become false. |
| */ |
| public void testException() { |
| final FailTask e = new FailTask(); |
| |
| try { |
| e.run(null); |
| fail("Didn't throw exception"); |
| } catch (RuntimeException expected) { |
| } |
| assertFalse(e.isRunningForTest()); |
| } |
| } |