1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements.  See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License.  You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.apache.harmony.tests.java.nio.channels;
18
19import java.io.IOException;
20import java.net.InetAddress;
21import java.net.InetSocketAddress;
22import java.nio.ByteBuffer;
23import java.nio.channels.ClosedChannelException;
24import java.nio.channels.Pipe;
25import java.nio.channels.SelectionKey;
26import java.nio.channels.ServerSocketChannel;
27import java.nio.channels.SocketChannel;
28
29import junit.framework.TestCase;
30
31/**
32 * Tests for Pipe.SinkChannel class
33 */
34public class SinkChannelTest extends TestCase {
35
36	private static final int BUFFER_SIZE = 5;
37
38	private static final String ISO8859_1 = "ISO8859-1";
39
40	private Pipe pipe;
41
42	private Pipe.SinkChannel sink;
43
44	private Pipe.SourceChannel source;
45
46	private ByteBuffer buffer;
47
48	private ByteBuffer positionedBuffer;
49
50	protected void setUp() throws Exception {
51		super.setUp();
52		pipe = Pipe.open();
53		sink = pipe.sink();
54		source = pipe.source();
55		buffer = ByteBuffer.wrap("bytes".getBytes(ISO8859_1));
56		positionedBuffer = ByteBuffer.wrap("12345bytes".getBytes(ISO8859_1));
57		positionedBuffer.position(BUFFER_SIZE);
58	}
59
60	/**
61	 * @tests java.nio.channels.Pipe.SinkChannel#validOps()
62	 */
63	public void test_validOps() {
64		assertEquals(SelectionKey.OP_WRITE, sink.validOps());
65	}
66
67	/**
68	 * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer)
69	 */
70	public void test_write_LByteBuffer() throws IOException {
71		ByteBuffer[] bufArray = { buffer, positionedBuffer };
72		boolean[] sinkBlockingMode = { true, true, false, false };
73		boolean[] sourceBlockingMode = { true, false, true, false };
74		int oldPosition;
75		int currentPosition;
76		for (int i = 0; i < sinkBlockingMode.length; ++i) {
77			sink.configureBlocking(sinkBlockingMode[i]);
78			source.configureBlocking(sourceBlockingMode[i]);
79			// if sink and source both are blocking mode, source only needs read
80			// once to get what sink write.
81			boolean isBlocking = sinkBlockingMode[i] && sourceBlockingMode[i];
82			for (ByteBuffer buf : bufArray) {
83				buf.mark();
84				oldPosition = buf.position();
85				sink.write(buf);
86				ByteBuffer readBuf = ByteBuffer.allocate(BUFFER_SIZE);
87				int totalCount = 0;
88				do {
89					int count = source.read(readBuf);
90					if (count > 0) {
91						totalCount += count;
92					}
93				} while (totalCount != BUFFER_SIZE && !isBlocking);
94				currentPosition = buf.position();
95				assertEquals(BUFFER_SIZE, currentPosition - oldPosition);
96				assertEquals("bytes", new String(readBuf.array(), ISO8859_1));
97				buf.reset();
98			}
99		}
100	}
101
102	/**
103	 * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer)
104	 */
105	public void test_write_LByteBuffer_mutliThread() throws IOException,
106	        InterruptedException {
107        final int THREAD_NUM = 20;
108        final byte[] strbytes = "bytes".getBytes(ISO8859_1);
109        Thread[] thread = new Thread[THREAD_NUM];
110        for (int i = 0; i < THREAD_NUM; i++) {
111            thread[i] = new Thread() {
112                public void run() {
113                    try {
114                        sink.write(ByteBuffer.wrap(strbytes));
115                    } catch (IOException e) {
116                        throw new RuntimeException(e);
117                    }
118                }
119            };
120        }
121        for (int i = 0; i < THREAD_NUM; i++) {
122            thread[i].start();
123        }
124        for (int i = 0; i < THREAD_NUM; i++) {
125            thread[i].join();
126        }
127        ByteBuffer readBuf = ByteBuffer.allocate(THREAD_NUM * BUFFER_SIZE);
128
129        long totalCount = 0;
130        do {
131            long count = source.read(readBuf);
132            if (count < 0) {
133                break;
134            }
135            totalCount += count;
136        } while (totalCount != (THREAD_NUM * BUFFER_SIZE));
137
138        StringBuffer buf = new StringBuffer();
139        for (int i = 0; i < THREAD_NUM; i++) {
140            buf.append("bytes");
141        }
142        String readString = buf.toString();
143        assertEquals(readString, new String(readBuf.array(), ISO8859_1));
144	}
145
146	/**
147	 * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer)
148	 */
149	public void test_write_LByteBuffer_Exception() throws IOException {
150		// write null ByteBuffer
151		ByteBuffer nullBuf = null;
152		try {
153			sink.write(nullBuf);
154			fail("should throw NullPointerException");
155		} catch (NullPointerException e) {
156			// expected
157		}
158	}
159
160    public void test_write_LByteBuffer_SourceClosed() throws IOException {
161        source.close();
162        try {
163            int written = sink.write(buffer);
164            fail();
165        } catch (IOException expected) {
166        }
167    }
168
169    public void test_write_LByteBuffer_SinkClosed() throws IOException {
170        sink.close();
171        try {
172            sink.write(buffer);
173            fail("should throw ClosedChannelException");
174        } catch (ClosedChannelException expected) {
175        }
176    }
177
178	/**
179	 * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer[])
180	 */
181	public void test_write_$LByteBuffer() throws IOException {
182		ByteBuffer[] bufArray = { buffer, positionedBuffer };
183		boolean[] sinkBlockingMode = { true, true, false, false };
184		boolean[] sourceBlockingMode = { true, false, true, false };
185		for (int i = 0; i < sinkBlockingMode.length; ++i) {
186			sink.configureBlocking(sinkBlockingMode[i]);
187			source.configureBlocking(sourceBlockingMode[i]);
188			buffer.position(0);
189			positionedBuffer.position(BUFFER_SIZE);
190			sink.write(bufArray);
191			// if sink and source both are blocking mode, source only needs read
192			// once to get what sink write.
193			boolean isBlocking = sinkBlockingMode[i] && sourceBlockingMode[i];
194			for (int j = 0; j < bufArray.length; ++j) {
195				ByteBuffer readBuf = ByteBuffer.allocate(BUFFER_SIZE);
196				int totalCount = 0;
197				do {
198					int count = source.read(readBuf);
199					if (count < 0) {
200						break;
201					}
202					totalCount += count;
203				} while (totalCount != BUFFER_SIZE && !isBlocking);
204				assertEquals("bytes", new String(readBuf.array(), ISO8859_1));
205			}
206			assertEquals(BUFFER_SIZE, buffer.position());
207			assertEquals(10, positionedBuffer.position());
208		}
209	}
210
211	/**
212	 * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer[])
213	 */
214	public void test_write_$LByteBuffer_Exception() throws IOException {
215		// write null ByteBuffer[]
216		ByteBuffer[] nullBufArrayRef = null;
217		try {
218			sink.write(nullBufArrayRef);
219			fail("should throw NullPointerException");
220		} catch (NullPointerException e) {
221			// expected
222		}
223
224		// write ByteBuffer[] contains null element
225		ByteBuffer nullBuf = null;
226		ByteBuffer[] nullBufArray = { buffer, nullBuf };
227		try {
228			sink.write(nullBufArray);
229			fail("should throw NullPointerException");
230		} catch (NullPointerException e) {
231			// expected
232		}
233	}
234
235    public void test_write_$LByteBuffer_SourceClosed() throws IOException {
236        ByteBuffer[] bufArray = { buffer };
237        source.close();
238        try {
239            long written = sink.write(bufArray);
240            fail();
241        } catch (IOException expected) {
242        }
243    }
244
245	/**
246	 * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer[])
247	 */
248	public void test_write_$LByteBuffer_SinkClosed() throws IOException {
249		ByteBuffer[] bufArray = { buffer };
250		sink.close();
251		try {
252			sink.write(bufArray);
253			fail("should throw ClosedChannelException");
254		} catch (ClosedChannelException e) {
255			// expected
256		}
257
258		ByteBuffer[] nullBufArrayRef = null;
259		try {
260			sink.write(nullBufArrayRef);
261			fail("should throw NullPointerException");
262		} catch (NullPointerException e) {
263			// expected
264		}
265
266		ByteBuffer nullBuf = null;
267		ByteBuffer[] nullBufArray = { nullBuf };
268		// write ByteBuffer[] contains null element
269		try {
270			sink.write(nullBufArray);
271			fail("should throw ClosedChannelException");
272		} catch (ClosedChannelException e) {
273			// expected
274		}
275	}
276
277	/**
278	 * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer[], int, int)
279	 */
280	public void test_write_$LByteBufferII() throws IOException {
281		ByteBuffer[] bufArray = { buffer, positionedBuffer };
282		boolean[] sinkBlockingMode = { true, true, false, false };
283		boolean[] sourceBlockingMode = { true, false, true, false };
284		for (int i = 0; i < sinkBlockingMode.length; ++i) {
285			sink.configureBlocking(sinkBlockingMode[i]);
286			source.configureBlocking(sourceBlockingMode[i]);
287			positionedBuffer.position(BUFFER_SIZE);
288			sink.write(bufArray, 1, 1);
289			// if sink and source both are blocking mode, source only needs read
290			// once to get what sink write.
291			boolean isBlocking = sinkBlockingMode[i] && sourceBlockingMode[i];
292			ByteBuffer readBuf = ByteBuffer.allocate(BUFFER_SIZE);
293			int totalCount = 0;
294			do {
295				int count = source.read(readBuf);
296				if (count < 0) {
297					break;
298				}
299				totalCount += count;
300			} while (totalCount != BUFFER_SIZE && !isBlocking);
301			assertEquals("bytes", new String(readBuf.array(), ISO8859_1));
302			assertEquals(10, positionedBuffer.position());
303		}
304	}
305
306    public void test_write_$LByteBufferII_Exception() throws IOException {
307        try {
308            sink.write(null, 0, 1);
309            fail();
310        } catch (NullPointerException expected) {
311        }
312
313        try {
314            sink.write(new ByteBuffer[2], 0, -1);
315            fail();
316        } catch (IndexOutOfBoundsException expected) {
317        }
318
319        // write ByteBuffer[] contains null element
320        ByteBuffer nullBuf = null;
321        ByteBuffer[] nullBufArray = { nullBuf };
322        try {
323            sink.write(nullBufArray, 0, 1);
324            fail("should throw NullPointerException");
325        } catch (NullPointerException e) {
326            // expected
327        }
328
329        try {
330            sink.write(nullBufArray, 0, -1);
331            fail("should throw IndexOutOfBoundsException");
332        } catch (IndexOutOfBoundsException e) {
333            // expected
334        }
335
336        ByteBuffer[] bufArray = { buffer, nullBuf };
337        try {
338            sink.write(bufArray, 0, -1);
339            fail("should throw IndexOutOfBoundsException");
340        } catch (IndexOutOfBoundsException e) {
341            // expected
342        }
343
344        try {
345            sink.write(bufArray, -1, 0);
346            fail("should throw IndexOutOfBoundsException");
347        } catch (IndexOutOfBoundsException e) {
348            // expected
349        }
350
351        try {
352            sink.write(bufArray, -1, 1);
353            fail("should throw IndexOutOfBoundsException");
354        } catch (IndexOutOfBoundsException e) {
355            // expected
356        }
357
358        try {
359            sink.write(bufArray, 0, 3);
360            fail("should throw IndexOutOfBoundsException");
361        } catch (IndexOutOfBoundsException e) {
362            // expected
363        }
364
365        try {
366            sink.write(bufArray, 0, 2);
367            fail("should throw NullPointerException");
368        } catch (NullPointerException e) {
369            // expected
370        }
371    }
372
373    public void test_write_$LByteBufferII_SourceClosed() throws IOException {
374        ByteBuffer[] bufArray = { buffer };
375        source.close();
376
377        try {
378            long written = sink.write(bufArray, 0, 1);
379            fail();
380        } catch (IOException expected) {
381        }
382    }
383
384    public void test_write_$LByteBufferII_SinkClosed() throws IOException {
385        ByteBuffer[] bufArray = { buffer };
386        sink.close();
387        try {
388            sink.write(bufArray, 0, 1);
389            fail();
390        } catch (ClosedChannelException expected) {
391        }
392
393        try {
394            sink.write(null, 0, 1);
395            fail();
396        } catch (NullPointerException expected) {
397        }
398        try {
399            sink.write(new ByteBuffer[2], 0, -1);
400            fail();
401        } catch (IndexOutOfBoundsException expected) {
402        }
403
404        // write ByteBuffer[] contains null element
405        ByteBuffer nullBuf = null;
406        ByteBuffer[] nullBufArray = { nullBuf };
407        try {
408            sink.write(nullBufArray, 0, 1);
409            fail("should throw ClosedChannelException");
410        } catch (ClosedChannelException e) {
411            // expected
412        }
413        // illegal array index
414        try {
415            sink.write(nullBufArray, 0, -1);
416            fail("should throw IndexOutOfBoundsException");
417        } catch (IndexOutOfBoundsException e) {
418            // expected
419        }
420
421        ByteBuffer[] bufArray2 = { buffer, nullBuf };
422        // illegal array index
423        try {
424            sink.write(bufArray2, 0, -1);
425            fail("should throw IndexOutOfBoundsException");
426        } catch (IndexOutOfBoundsException e) {
427            // expected
428        }
429
430        try {
431            sink.write(bufArray2, -1, 0);
432            fail("should throw IndexOutOfBoundsException");
433        } catch (IndexOutOfBoundsException e) {
434            // expected
435        }
436
437        try {
438            sink.write(bufArray2, -1, 1);
439            fail("should throw IndexOutOfBoundsException");
440        } catch (IndexOutOfBoundsException e) {
441            // expected
442        }
443
444        try {
445            sink.write(bufArray2, 0, 3);
446            fail("should throw IndexOutOfBoundsException");
447        } catch (IndexOutOfBoundsException e) {
448            // expected
449        }
450
451        try {
452            sink.write(bufArray2, 0, 2);
453            fail("should throw ClosedChannelException");
454        } catch (ClosedChannelException e) {
455            // expected
456        }
457    }
458
459    public void test_close() throws IOException {
460        sink.close();
461        assertFalse(sink.isOpen());
462    }
463
464    public void test_socketChannel_read_close() throws Exception {
465        ServerSocketChannel ssc = ServerSocketChannel.open();
466        ssc.socket().bind(new InetSocketAddress(InetAddress.getLocalHost(),49999));
467        SocketChannel sc = SocketChannel.open();
468        ByteBuffer buf = null;
469        try{
470            sc.write(buf);
471            fail("should throw NPE");
472        }catch (NullPointerException e){
473            // expected
474        }
475        sc.connect(new InetSocketAddress(InetAddress.getLocalHost(),49999));
476        SocketChannel sock = ssc.accept();
477        ssc.close();
478        sc.close();
479        try{
480            sc.write(buf);
481            fail("should throw NPE");
482        }catch (NullPointerException e){
483            // expected
484        }
485        sock.close();
486    }
487
488    public void test_socketChannel_read_write() throws Exception {
489        ServerSocketChannel ssc = ServerSocketChannel.open();
490        ssc.socket().bind(new InetSocketAddress(InetAddress.getLocalHost(),49999));
491        SocketChannel sc = SocketChannel.open();
492        sc.connect(new InetSocketAddress(InetAddress.getLocalHost(),49999));
493        SocketChannel sock = ssc.accept();
494        ByteBuffer[] buf = {ByteBuffer.allocate(10),null};
495        try {
496            sc.write(buf,0,2);
497            fail("should throw NPE");
498        } catch (NullPointerException expected) {
499        }
500        ssc.close();
501        sc.close();
502        ByteBuffer target = ByteBuffer.allocate(10);
503        assertEquals(-1, sock.read(target));
504    }
505}
506