View Javadoc
1   package com.github.davidmoten.rtree;
2   
3   import static com.github.davidmoten.rtree.RTreeTest.e;
4   import static org.junit.Assert.assertEquals;
5   import static org.junit.Assert.assertTrue;
6   
7   import java.util.ArrayList;
8   import java.util.Arrays;
9   import java.util.Collections;
10  import java.util.HashSet;
11  import java.util.List;
12  import java.util.Set;
13  
14  import org.junit.Test;
15  import org.mockito.Mockito;
16  
17  import com.github.davidmoten.junit.Asserts;
18  import com.github.davidmoten.rtree.geometry.Geometry;
19  import com.github.davidmoten.rtree.geometry.Rectangle;
20  import com.github.davidmoten.rtree.internal.util.ImmutableStack;
21  
22  import rx.Subscriber;
23  import rx.Subscription;
24  import rx.functions.Func1;
25  
26  public class BackpressureTest {
27  
28      @Test
29      public void testConstructorIsPrivate() {
30          Asserts.assertIsUtilityClass(Backpressure.class);
31      }
32  
33      @SuppressWarnings("unchecked")
34      @Test
35      public void testBackpressureSearch() {
36          Subscriber<Object> sub = Mockito.mock(Subscriber.class);
37          ImmutableStack<NodePosition<Object, Geometry>> stack = ImmutableStack.empty();
38          Func1<Geometry, Boolean> condition = Mockito.mock(Func1.class);
39          Backpressure.search(condition, sub, stack, 1);
40          Mockito.verify(sub, Mockito.never()).onNext(Mockito.any());
41      }
42  
43      @Test
44      public void testBackpressureSearchNodeWithConditionThatAlwaysReturnsFalse() {
45          RTree<Object, Rectangle> tree = RTree.maxChildren(3).<Object, Rectangle> create()
46                  .add(e(1)).add(e(3)).add(e(5)).add(e(7));
47  
48          Set<Entry<Object, Rectangle>> found = new HashSet<Entry<Object, Rectangle>>();
49          tree.search(e(1).geometry()).subscribe(backpressureSubscriber(found));
50          assertEquals(1, found.size());
51      }
52  
53      @SuppressWarnings("unchecked")
54      @Test
55      public void testRequestZero() {
56          Subscriber<Object> sub = new Subscriber<Object>() {
57  
58              @Override
59              public void onCompleted() {
60              }
61  
62              @Override
63              public void onError(Throwable e) {
64              }
65  
66              @Override
67              public void onNext(Object t) {
68  
69              }
70          };
71          sub.add(new Subscription() {
72              volatile boolean subscribed = true;
73  
74              @Override
75              public void unsubscribe() {
76                  subscribed = false;
77              }
78  
79              @Override
80              public boolean isUnsubscribed() {
81                  return !subscribed;
82              }
83          });
84          Node<Object, Geometry> node = Mockito.mock(Node.class);
85          NodePosition<Object, Geometry> np = new NodePosition<Object, Geometry>(node, 1);
86          ImmutableStack<NodePosition<Object, Geometry>> stack = ImmutableStack
87                  .<NodePosition<Object, Geometry>> empty().push(np);
88          Func1<Geometry, Boolean> condition = Mockito.mock(Func1.class);
89          ImmutableStack<NodePosition<Object, Geometry>> stack2 = Backpressure.search(condition, sub,
90                  stack, 0);
91          assertTrue(stack2 == stack);
92      }
93  
94      @SuppressWarnings("unchecked")
95      @Test
96      public void testRequestZeroWhenUnsubscribed() {
97          Subscriber<Object> sub = new Subscriber<Object>() {
98  
99              @Override
100             public void onCompleted() {
101             }
102 
103             @Override
104             public void onError(Throwable e) {
105             }
106 
107             @Override
108             public void onNext(Object t) {
109 
110             }
111         };
112         sub.add(new Subscription() {
113 
114             volatile boolean subscribed = true;
115 
116             @Override
117             public void unsubscribe() {
118                 subscribed = false;
119             }
120 
121             @Override
122             public boolean isUnsubscribed() {
123                 return !subscribed;
124             }
125         });
126         sub.unsubscribe();
127         Node<Object, Geometry> node = Mockito.mock(Node.class);
128         NodePosition<Object, Geometry> np = new NodePosition<Object, Geometry>(node, 1);
129         ImmutableStack<NodePosition<Object, Geometry>> stack = ImmutableStack
130                 .<NodePosition<Object, Geometry>> empty().push(np);
131         Func1<Geometry, Boolean> condition = Mockito.mock(Func1.class);
132         ImmutableStack<NodePosition<Object, Geometry>> stack2 = Backpressure.search(condition, sub,
133                 stack, 1);
134         assertTrue(stack2.isEmpty());
135     }
136 
137     @Test
138     public void testBackpressureIterateWhenNodeHasMaxChildrenAndIsRoot() {
139         Entry<Object, Rectangle> e1 = RTreeTest.e(1);
140         List<Entry<Object, Rectangle>> list = Arrays.asList(e1, e1, e1, e1);
141         RTree<Object, Rectangle> tree = RTree.star().maxChildren(4).<Object, Rectangle> create()
142                 .add(list);
143         HashSet<Entry<Object, Rectangle>> expected = new HashSet<Entry<Object, Rectangle>>(list);
144         final HashSet<Entry<Object, Rectangle>> found = new HashSet<Entry<Object, Rectangle>>();
145         tree.entries().subscribe(backpressureSubscriber(found));
146         assertEquals(expected, found);
147     }
148 
149     @Test
150     public void testBackpressureRequestZero() {
151         Entry<Object, Rectangle> e1 = RTreeTest.e(1);
152         List<Entry<Object, Rectangle>> list = Arrays.asList(e1, e1, e1, e1);
153         RTree<Object, Rectangle> tree = RTree.star().maxChildren(4).<Object, Rectangle> create()
154                 .add(list);
155         HashSet<Entry<Object, Rectangle>> expected = new HashSet<Entry<Object, Rectangle>>(list);
156         final HashSet<Entry<Object, Rectangle>> found = new HashSet<Entry<Object, Rectangle>>();
157         tree.entries().subscribe(new Subscriber<Entry<Object, Rectangle>>() {
158 
159             @Override
160             public void onStart() {
161                 request(1);
162             }
163 
164             @Override
165             public void onCompleted() {
166 
167             }
168 
169             @Override
170             public void onError(Throwable e) {
171 
172             }
173 
174             @Override
175             public void onNext(Entry<Object, Rectangle> t) {
176                 found.add(t);
177                 request(0);
178             }
179         });
180         assertEquals(expected, found);
181     }
182 
183     @Test
184     public void testBackpressureIterateWhenNodeHasMaxChildrenAndIsNotRoot() {
185         Entry<Object, Rectangle> e1 = RTreeTest.e(1);
186         List<Entry<Object, Rectangle>> list = new ArrayList<Entry<Object, Rectangle>>();
187         for (int i = 1; i <= 17; i++)
188             list.add(e1);
189         RTree<Object, Rectangle> tree = RTree.star().maxChildren(4).<Object, Rectangle> create()
190                 .add(list);
191         HashSet<Entry<Object, Rectangle>> expected = new HashSet<Entry<Object, Rectangle>>(list);
192         final HashSet<Entry<Object, Rectangle>> found = new HashSet<Entry<Object, Rectangle>>();
193         tree.entries().subscribe(backpressureSubscriber(found));
194         assertEquals(expected, found);
195     }
196 
197     @Test
198     public void testBackpressureIterateWhenConditionFailsAgainstNonLeafNode() {
199         Entry<Object, Rectangle> e1 = e(1);
200         List<Entry<Object, Rectangle>> list = new ArrayList<Entry<Object, Rectangle>>();
201         for (int i = 1; i <= 17; i++)
202             list.add(e1);
203         list.add(e(2));
204         RTree<Object, Rectangle> tree = RTree.star().maxChildren(4).<Object, Rectangle> create()
205                 .add(list);
206         HashSet<Entry<Object, Rectangle>> expected = new HashSet<Entry<Object, Rectangle>>(list);
207         final HashSet<Entry<Object, Rectangle>> found = new HashSet<Entry<Object, Rectangle>>();
208         tree.entries().subscribe(backpressureSubscriber(found));
209         assertEquals(expected, found);
210     }
211 
212     @Test
213     public void testBackpressureIterateWhenConditionFailsAgainstLeafNode() {
214         Entry<Object, Rectangle> e3 = e(3);
215         RTree<Object, Rectangle> tree = RTree.star().maxChildren(4).<Object, Rectangle> create()
216                 .add(e(1)).add(e3);
217         Set<Entry<Object, Rectangle>> expected = Collections.singleton(e3);
218         final Set<Entry<Object, Rectangle>> found = new HashSet<Entry<Object, Rectangle>>();
219         tree.search(e3.geometry()).subscribe(backpressureSubscriber(found));
220         assertEquals(expected, found);
221     }
222 
223     @Test
224     public void testBackpressureFastPathNotInitiatedTwice() {
225         Entry<Object, Rectangle> e3 = e(3);
226         RTree<Object, Rectangle> tree = RTree.star().maxChildren(4).<Object, Rectangle> create()
227                 .add(e(1)).add(e3);
228         Set<Entry<Object, Rectangle>> expected = Collections.singleton(e3);
229         final Set<Entry<Object, Rectangle>> found = new HashSet<Entry<Object, Rectangle>>();
230         tree.search(e3.geometry()).subscribe(new Subscriber<Entry<Object, Rectangle>>() {
231 
232             @Override
233             public void onCompleted() {
234 
235             }
236 
237             @Override
238             public void onError(Throwable e) {
239 
240             }
241 
242             @Override
243             public void onNext(Entry<Object, Rectangle> t) {
244                 found.add(t);
245                 request(Long.MAX_VALUE);
246             }
247         });
248         assertEquals(expected, found);
249     }
250 
251     private static Subscriber<Entry<Object, Rectangle>> backpressureSubscriber(
252             final Set<Entry<Object, Rectangle>> found) {
253         return new Subscriber<Entry<Object, Rectangle>>() {
254 
255             @Override
256             public void onStart() {
257                 request(1);
258             }
259 
260             @Override
261             public void onCompleted() {
262 
263             }
264 
265             @Override
266             public void onError(Throwable e) {
267 
268             }
269 
270             @Override
271             public void onNext(Entry<Object, Rectangle> t) {
272                 found.add(t);
273                 request(1);
274             }
275         };
276     }
277 
278 }