View Javadoc
1   /*
2    * Copyright (C) 2009-2010, Google Inc. and others
3    *
4    * This program and the accompanying materials are made available under the
5    * terms of the Eclipse Distribution License v. 1.0 which is available at
6    * https://www.eclipse.org/org/documents/edl-v10.php.
7    *
8    * SPDX-License-Identifier: BSD-3-Clause
9    */
10  
11  package org.eclipse.jgit.util.io;
12  
13  import static org.junit.Assert.assertArrayEquals;
14  import static org.junit.Assert.assertEquals;
15  import static org.junit.Assert.assertFalse;
16  import static org.junit.Assert.assertTrue;
17  import static org.junit.Assert.fail;
18  
19  import java.io.IOException;
20  import java.io.InterruptedIOException;
21  import java.io.PipedInputStream;
22  import java.io.PipedOutputStream;
23  import java.util.Arrays;
24  import java.util.List;
25  
26  import org.eclipse.jgit.util.IO;
27  import org.junit.After;
28  import org.junit.Before;
29  import org.junit.Test;
30  
31  public class TimeoutInputStreamTest {
32  	private static final int timeout = 250;
33  
34  	private PipedOutputStream out;
35  
36  	private PipedInputStream in;
37  
38  	private InterruptTimer timer;
39  
40  	private TimeoutInputStream is;
41  
42  	private long start;
43  
44  	@Before
45  	public void setUp() throws Exception {
46  		out = new PipedOutputStream();
47  		in = new PipedInputStream(out);
48  		timer = new InterruptTimer();
49  		is = new TimeoutInputStream(in, timer);
50  		is.setTimeout(timeout);
51  	}
52  
53  	@After
54  	public void tearDown() throws Exception {
55  		timer.terminate();
56  		for (Thread t : active())
57  			assertFalse(t instanceof InterruptTimer.AlarmThread);
58  	}
59  
60  	@Test
61  	public void testTimeout_readByte_Success1() throws IOException {
62  		out.write('a');
63  		assertEquals('a', is.read());
64  	}
65  
66  	@Test
67  	public void testTimeout_readByte_Success2() throws IOException {
68  		final byte[] exp = new byte[] { 'a', 'b', 'c' };
69  		out.write(exp);
70  		assertEquals(exp[0], is.read());
71  		assertEquals(exp[1], is.read());
72  		assertEquals(exp[2], is.read());
73  		out.close();
74  		assertEquals(-1, is.read());
75  	}
76  
77  	@Test
78  	public void testTimeout_readByte_Timeout() throws IOException {
79  		beginRead();
80  		try {
81  			is.read();
82  			fail("incorrectly read a byte");
83  		} catch (InterruptedIOException e) {
84  			// expected
85  		}
86  		assertTimeout();
87  	}
88  
89  	@Test
90  	public void testTimeout_readBuffer_Success1() throws IOException {
91  		final byte[] exp = new byte[] { 'a', 'b', 'c' };
92  		final byte[] act = new byte[exp.length];
93  		out.write(exp);
94  		IO.readFully(is, act, 0, act.length);
95  		assertArrayEquals(exp, act);
96  	}
97  
98  	@Test
99  	public void testTimeout_readBuffer_Success2() throws IOException {
100 		final byte[] exp = new byte[] { 'a', 'b', 'c' };
101 		final byte[] act = new byte[exp.length];
102 		out.write(exp);
103 		IO.readFully(is, act, 0, 1);
104 		IO.readFully(is, act, 1, 1);
105 		IO.readFully(is, act, 2, 1);
106 		assertArrayEquals(exp, act);
107 	}
108 
109 	@Test
110 	public void testTimeout_readBuffer_Timeout() throws IOException {
111 		beginRead();
112 		try {
113 			IO.readFully(is, new byte[512], 0, 512);
114 			fail("incorrectly read bytes");
115 		} catch (InterruptedIOException e) {
116 			// expected
117 		}
118 		assertTimeout();
119 	}
120 
121 	@Test
122 	public void testTimeout_skip_Success() throws IOException {
123 		final byte[] exp = new byte[] { 'a', 'b', 'c' };
124 		out.write(exp);
125 		assertEquals(2, is.skip(2));
126 		assertEquals('c', is.read());
127 	}
128 
129 	@Test
130 	public void testTimeout_skip_Timeout() throws IOException {
131 		beginRead();
132 		try {
133 			is.skip(1024);
134 			fail("incorrectly skipped bytes");
135 		} catch (InterruptedIOException e) {
136 			// expected
137 		}
138 		assertTimeout();
139 	}
140 
141 	private void beginRead() {
142 		start = now();
143 	}
144 
145 	private void assertTimeout() {
146 		// Our timeout was supposed to be ~250 ms. Since this is a timing
147 		// test we can't assume we spent *exactly* the timeout period, as
148 		// there may be other activity going on in the system. Instead we
149 		// look for the delta between the start and end times to be within
150 		// 50 ms of the expected timeout.
151 		//
152 		final long wait = now() - start;
153 		assertTrue("waited only " + wait + " ms", timeout - wait < 50);
154 	}
155 
156 	private static List<Thread> active() {
157 		Thread[] all = new Thread[16];
158 		int n = Thread.currentThread().getThreadGroup().enumerate(all);
159 		while (n == all.length) {
160 			all = new Thread[all.length * 2];
161 			n = Thread.currentThread().getThreadGroup().enumerate(all);
162 		}
163 		return Arrays.asList(all).subList(0, n);
164 	}
165 
166 	private static long now() {
167 		return System.currentTimeMillis();
168 	}
169 }