]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scenegraph/testcases/org/simantics/scenegraph/tests/LookupServiceSynchronizationTest.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scenegraph / testcases / org / simantics / scenegraph / tests / LookupServiceSynchronizationTest.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.scenegraph.tests;\r
13 \r
14 import static junit.framework.Assert.assertEquals;\r
15 import static junit.framework.Assert.assertSame;\r
16 \r
17 import java.util.ArrayList;\r
18 import java.util.List;\r
19 import java.util.UUID;\r
20 import java.util.concurrent.BrokenBarrierException;\r
21 import java.util.concurrent.CyclicBarrier;\r
22 import java.util.concurrent.Semaphore;\r
23 import java.util.concurrent.atomic.AtomicBoolean;\r
24 \r
25 import org.junit.Test;\r
26 import org.simantics.scenegraph.INode;\r
27 import org.simantics.scenegraph.ParentNode;\r
28 import org.simantics.scenegraph.g2d.G2DParentNode;\r
29 import org.simantics.scenegraph.g2d.G2DSceneGraph;\r
30 import org.simantics.scenegraph.g2d.nodes.DataNode;\r
31 import org.simantics.scenegraph.g2d.nodes.NavigationNode;\r
32 import org.simantics.scenegraph.utils.NodeUtil;\r
33 \r
34 \r
35 /**\r
36  * @author Tuukka Lehtonen\r
37  */\r
38 public class LookupServiceSynchronizationTest {\r
39 \r
40     public static final int ITERATIONS        = 10;\r
41     public static final int ITERATION_TIME_MS = 1000;\r
42     public static final int THREADS           = 16;\r
43 \r
44     AtomicBoolean           endTest;\r
45     CyclicBarrier           startBarrier;\r
46     Semaphore               ended;\r
47 \r
48     G2DSceneGraph           root              = new G2DSceneGraph();\r
49     List<INode>             nodes             = new ArrayList<INode>();\r
50     List<String>            nodeIds           = new ArrayList<String>();\r
51     List<String>            mappedIds         = new ArrayList<String>();\r
52 \r
53     List<Throwable>         errors            = new ArrayList<Throwable>();\r
54 \r
55     public class Lookup implements Runnable {\r
56         String id;\r
57         INode node;\r
58         public Lookup(String id, INode node) {\r
59             this.id = id;\r
60             this.node = node;\r
61         }\r
62         @Override\r
63         public void run() {\r
64             try {\r
65                 System.out.println("started " + Thread.currentThread().getName());\r
66                 System.out.flush();\r
67                 startBarrier.await();\r
68                 while (!endTest.get()) {\r
69                     Thread.yield();\r
70                     INode n = NodeUtil.lookup(this.node, this.id);\r
71                     String id = NodeUtil.lookupId(this.node);\r
72                     if (n != null)\r
73                         assertSame(this.node, n);\r
74                     if (id != null)\r
75                         assertSame(this.id, id);\r
76                 }\r
77             } catch (InterruptedException e) {\r
78                 errors.add(e);\r
79             } catch (BrokenBarrierException e) {\r
80                 errors.add(e);\r
81             } finally {\r
82                 System.out.println("ending " + Thread.currentThread().getName());\r
83                 System.out.flush();\r
84                 ended.release();\r
85             }\r
86         }\r
87     }\r
88 \r
89     public class Mapper implements Runnable {\r
90         String id;\r
91         INode node;\r
92         public Mapper(String id, INode node) {\r
93             this.id = id;\r
94             this.node = node;\r
95         }\r
96         @Override\r
97         public void run() {\r
98             try {\r
99                 System.out.println("started " + Thread.currentThread().getName());\r
100                 System.out.flush();\r
101                 startBarrier.await();\r
102                 for (int i = 0; !endTest.get(); ++i) {\r
103                     Thread.yield();\r
104                     NodeUtil.map(node, id);\r
105                     if ((i & 1) == 0)\r
106                         NodeUtil.unmap(node);\r
107                     else\r
108                         root.unmap(id);\r
109                 }\r
110             } catch (InterruptedException e) {\r
111                 errors.add(e);\r
112             } catch (BrokenBarrierException e) {\r
113                 errors.add(e);\r
114             } finally {\r
115                 System.out.println("ending " + Thread.currentThread().getName());\r
116                 System.out.flush();\r
117                 ended.release();\r
118             }\r
119         }\r
120     }\r
121 \r
122     <T extends INode> T addAndMapNode(ParentNode<?> parent, String id, Class<T> clazz) {\r
123         T node = parent.addNode(id, clazz);\r
124         nodes.add( node );\r
125         nodeIds.add( id );\r
126         NodeUtil.map(node, id);\r
127         return node;\r
128     }\r
129 \r
130     <T extends INode> T addNode(ParentNode<?> parent, String id, Class<T> clazz) {\r
131         T node = parent.addNode(id, clazz);\r
132         nodes.add( node );\r
133         nodeIds.add( id );\r
134         return node;\r
135     }\r
136 \r
137     <T extends INode> T addNode(ParentNode<?> parent, Class<T> clazz) {\r
138         return addNode(parent, UUID.randomUUID().toString(), clazz);\r
139     }\r
140 \r
141     @Test\r
142     public void testLookup() throws Exception {\r
143         NavigationNode nav = addAndMapNode(root, "navigation", NavigationNode.class);\r
144         DataNode data = addAndMapNode(root, "data", DataNode.class);\r
145         G2DParentNode elements = addNode(nav, "elements", G2DParentNode.class);\r
146         @SuppressWarnings("unused")\r
147         G2DParentNode ghosts = addNode(nav, "ghosts", G2DParentNode.class);\r
148 \r
149         // Basic checks\r
150         assertSame(nav, root.lookupNode("navigation"));\r
151         assertSame(data, root.lookupNode("data"));\r
152         assertSame(nav, NodeUtil.lookup(nav, "navigation"));\r
153         assertSame(data, NodeUtil.lookup(data, "data"));\r
154 \r
155         for (int iter = 1; iter <= ITERATIONS; ++iter) {\r
156             System.out.println("Starting iteration " + iter);\r
157             System.out.flush();\r
158             // Start iteration\r
159             endTest = new AtomicBoolean(false);\r
160             startBarrier = new CyclicBarrier(THREADS * 2 + 1);\r
161             ended = new Semaphore(0);\r
162 \r
163             for (int i = 0; i < THREADS; ++i) {\r
164                 String id = UUID.randomUUID().toString();\r
165                 INode node = addNode(elements, id, G2DParentNode.class);\r
166                 new Thread(new Mapper(id, node), "Mapper-" + i).start();\r
167                 new Thread(new Lookup(id, node), "Lookup-" + i).start();\r
168             }\r
169 \r
170             startBarrier.await();\r
171             // Sleep for the testing period\r
172             synchronized (this) {\r
173                 wait(ITERATION_TIME_MS);\r
174             }\r
175             // Wait for threads to end\r
176             System.out.println("Ending iteration " + iter);\r
177             System.out.flush();\r
178             endTest.set(true);\r
179             ended.acquire(2*THREADS);\r
180             System.out.println("Iteration " + iter + " ended");\r
181         }\r
182 \r
183         assertEquals(errors.size(), 0);\r
184     }\r
185 \r
186 }\r