Skip to main content
summaryrefslogblamecommitdiffstats
blob: 5c1aca4d1050fc09d736077426365d0e74bd91f3 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
                                                                                
                                                        








                                                                                
                                                           
 
                        


                                     
                                                       
                                         
                                             


                                









                                                           





                                             

                                                      
                                               



                                                 
                                                             



                                                
                                               


                                                 
                                                        





























                                                                                      
                                               
                                                                 

                                                                                                                      





                                                                   
                                               


                                                                        
                                               
                                                                 

                                                                                                                                   
















                                                                                                           

                                                                                                                      





                                                                   
                                                




                                                                        

                                                                                                                                   













                                                                                                            


                                                                                             

                           

                          
                                                        

                                                                 

                                                                                                                                



                                                                                            
                                                                                
                                                                        

                                                 

                           

                          











                                                                                 



                                                                                                                





                                                                        



                                                                                                                                                     





                                                       
                                                                                                                   
                                                
                                                                               


                                                                                                              
                                                                                       
                                                                                
                                                                                               










                                                                                



                                                                                                             




                                                                                                                           




                                                                           
                                 
                                                         



                         
                                             


                                                     



                                                  
                                                                                        


         
/*******************************************************************************
 * Copyright (c) 2007, 2010 Oracle. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0, which accompanies this distribution
 * and is available at http://www.eclipse.org/legal/epl-v10.html.
 * 
 * Contributors:
 *     Oracle - initial API and implementation
 ******************************************************************************/
package org.eclipse.jpt.utility.tests.internal;

import org.eclipse.jpt.utility.internal.SynchronizedObject;

@SuppressWarnings("nls")
public class SynchronizedObjectTests
	extends MultiThreadedTestCase
{
	private volatile SynchronizedObject<Object> so;
	volatile boolean timeoutOccurred;
	volatile Object value = new Object();
	volatile long startTime;
	volatile long endTime;
	volatile Object soValue;


	public SynchronizedObjectTests(String name) {
		super(name);
	}

	@Override
	protected void setUp() throws Exception {
		super.setUp();
		this.so = new SynchronizedObject<Object>();
		this.timeoutOccurred = false;
		this.startTime = 0;
		this.endTime = 0;
		this.soValue = null;
	}

	public void testAccessors() throws Exception {
		this.so.setValue(null);
		assertNull(this.so.getValue());
		assertFalse(this.so.isNotNull());
		assertTrue(this.so.isNull());

		this.so.setValue(this.value);
		assertEquals(this.value, this.so.getValue());
		assertTrue(this.so.isNotNull());
		assertFalse(this.so.isNull());

		this.so.setNull();
		assertNull(this.so.getValue());
		assertFalse(this.so.isNotNull());
		assertTrue(this.so.isNull());

		assertSame(this.so, this.so.getMutex());
	}

	public void testEquals() throws Exception {
		this.so.setValue(null);
		SynchronizedObject<Object> so2 = new SynchronizedObject<Object>(null);
		assertEquals(this.so, so2);

		this.so.setValue(this.value);
		assertFalse(this.so.equals(so2));

		so2.setValue(this.value);
		assertEquals(this.so, so2);
	}

	public void testHashCode() {
		this.so.setValue(this.value);
		assertEquals(this.value.hashCode(), this.so.hashCode());

		this.so.setValue(null);
		assertEquals(0, this.so.hashCode());
	}

	/**
	 * t2 will wait indefinitely until t1 sets the value to null
	 */
	public void testWaitUntilNull() throws Exception {
		this.verifyWaitUntilNull(0);
		// no timeout occurs...
		assertFalse(this.timeoutOccurred);
		// ...and the value should be set to null by t2
		assertNull(this.so.getValue());
		// make a reasonable guess about how long t2 took
		long time = this.calculateElapsedTime();
		assertTrue("t2 finished a bit early (expected value should be > " + TICK + "): " + time, time > TICK);
	}

	/**
	 * t2 will time out waiting for t1 to set the value to null
	 */
	public void testWaitUntilNullTimeout() throws Exception {
		this.verifyWaitUntilNull(TICK);
		// timeout occurs...
		assertTrue(this.timeoutOccurred);
		// ...and the value will eventually be set to null by t1
		assertNull(this.so.getValue());
		// make a reasonable guess about how long t2 took
		long time = this.calculateElapsedTime();
		assertTrue("t2 finished a bit late (expected value should be < " + THREE_TICKS + "): " + time, time < THREE_TICKS);
	}

	private void verifyWaitUntilNull(long t2Timeout) throws Exception {
		this.executeThreads(this.buildSetNullCommand(), this.buildWaitUntilNullCommand(t2Timeout));
	}

	/**
	 * t2 will wait indefinitely until t1 sets the value to null;
	 * then t2 will set the value to an object
	 */
	public void testWaitToSetValue() throws Exception {
		this.verifyWaitToSetValue(0);
		// no timeout occurs...
		assertFalse(this.timeoutOccurred);
		// ...and the value should be set to an object by t2
		assertTrue(this.so.isNotNull());
		// make a reasonable guess about how long t2 took
		long time = this.calculateElapsedTime();
		assertTrue("t2 finished a bit early (expected value should be > " + TICK + "): " + time, time > TICK);
	}

	/**
	 * t2 will time out waiting for t1 to set the value to null
	 */
	public void testWaitToSetValueTimeout() throws Exception {
		this.verifyWaitToSetValue(TICK);
		// timeout occurs...
		assertTrue(this.timeoutOccurred);
		// ...and the value will eventually be set to null by t1
		assertTrue(this.so.isNull());
		// make a reasonable guess about how long t2 took
		long time = this.calculateElapsedTime();
		assertTrue("t2 finished a bit late (expected value should be < " + THREE_TICKS + "): " + time, time < THREE_TICKS);
	}

	private void verifyWaitToSetValue(long t2Timeout) throws Exception {
		this.executeThreads(this.buildSetNullCommand(), this.buildWaitToSetValueCommand(t2Timeout));
	}

	/**
	 * t2 will wait until t1 is finished "initializing" the value;
	 * then t2 will get the newly-initialized value ("foo")
	 */
	public void testExecute() throws Exception {
		this.so.setValue(null);
		Runnable r1 = this.buildRunnable(this.buildInitializeValueCommand(), this.so, 0);
		// give t1 a head start of 100 ms
		Runnable r2 = this.buildRunnable(this.buildGetValueCommand(), this.so, TICK);
		Thread t1 = this.buildThread(r1);
		Thread t2 = this.buildThread(r2);
		t1.start();
		t2.start();
		t1.join();
		t2.join();
		assertEquals("foo", this.so.getValue());
		assertEquals("foo", this.soValue);
		// make a reasonable guess about how long t2 took
		long time = this.calculateElapsedTime();
		assertTrue("t2 finished a bit early (expected value should be > " + TWO_TICKS + "): " + time, time > TWO_TICKS);
	}

	private void executeThreads(Command t1Command, Command t2Command) throws Exception {
		this.so.setValue(this.value);
		Runnable r1 = this.buildRunnable(t1Command, this.so, TWO_TICKS);
		Runnable r2 = this.buildRunnable(t2Command, this.so, 0);
		Thread t1 = this.buildThread(r1);
		Thread t2 = this.buildThread(r2);
		t1.start();
		t2.start();
		t1.join();
		t2.join();
	}

	private Command buildSetNullCommand() {
		return new Command() {
			public void execute(SynchronizedObject<Object> sObject) {
				sObject.setNull();
			}
		};
	}

	private Command buildWaitUntilNullCommand(final long timeout) {
		return new Command() {
			public void execute(SynchronizedObject<Object> sObject) throws InterruptedException {
				SynchronizedObjectTests.this.startTime = System.currentTimeMillis();
				SynchronizedObjectTests.this.timeoutOccurred = ! sObject.waitUntilNull(timeout);
				SynchronizedObjectTests.this.endTime = System.currentTimeMillis();
			}
		};
	}

	private Command buildWaitToSetValueCommand(final long timeout) {
		return new Command() {
			public void execute(SynchronizedObject<Object> sObject) throws InterruptedException {
				SynchronizedObjectTests.this.startTime = System.currentTimeMillis();
				SynchronizedObjectTests.this.timeoutOccurred = ! sObject.waitToSetValue(SynchronizedObjectTests.this.value, timeout);
				SynchronizedObjectTests.this.endTime = System.currentTimeMillis();
			}
		};
	}

	private Command buildInitializeValueCommand() {
		return new Command() {
			public void execute(final SynchronizedObject<Object> sObject) throws InterruptedException {
				sObject.execute(
					new org.eclipse.jpt.utility.Command() {
						public void execute() {
							// pretend to perform some long initialization process
							try {
								Thread.sleep(5 * TICK);
							} catch (Exception ex) {
								throw new RuntimeException(ex);
							}
							sObject.setValue("foo");
						}
					}
				);
			}
		};
	}

	private Command buildGetValueCommand() {
		return new Command() {
			public void execute(SynchronizedObject<Object> sObject) throws InterruptedException {
				SynchronizedObjectTests.this.startTime = System.currentTimeMillis();
				SynchronizedObjectTests.this.soValue = sObject.getValue();
				SynchronizedObjectTests.this.endTime = System.currentTimeMillis();
			}
		};
	}

	private Runnable buildRunnable(final Command command, final SynchronizedObject<Object> sObject, final long sleep) {
		return new TestRunnable() {
			@Override
			protected void run_() throws InterruptedException {
				if (sleep != 0) {
					Thread.sleep(sleep);
				}
				command.execute(sObject);
			}
		};
	}

	private long calculateElapsedTime() {
		return this.endTime - this.startTime;
	}


	// ********** Command interface **********

	private interface Command {
		void execute(SynchronizedObject<Object> so) throws InterruptedException;
	}

}

Back to the top