View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one or more
3    *  contributor license agreements.  See the NOTICE file distributed with
4    *  this work for additional information regarding copyright ownership.
5    *  The ASF licenses this file to You under the Apache License, Version 2.0
6    *  (the "License"); you may not use this file except in compliance with
7    *  the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17  package org.apache.commons.compress.archivers.zip;
18  
19  import static org.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertNotNull;
21  import static org.junit.jupiter.api.Assertions.assertThrows;
22  import static org.mockito.ArgumentMatchers.any;
23  import static org.mockito.ArgumentMatchers.eq;
24  import static org.mockito.Mockito.mock;
25  import static org.mockito.Mockito.times;
26  import static org.mockito.Mockito.verify;
27  import static org.mockito.Mockito.when;
28  
29  import java.io.IOException;
30  import java.nio.ByteBuffer;
31  import java.nio.channels.FileChannel;
32  import java.nio.charset.StandardCharsets;
33  import java.nio.file.Path;
34  
35  import org.apache.commons.compress.AbstractTempDirTest;
36  import org.junit.jupiter.api.Test;
37  
38  /**
39   * Tests {@link FileRandomAccessOutputStream}.
40   */
41  public class FileRandomAccessOutputStreamTest extends AbstractTempDirTest {
42  
43      @Test
44      public void testChannelReturn() throws IOException {
45          final Path file = newTempPath("testChannel");
46          try (FileRandomAccessOutputStream stream = new FileRandomAccessOutputStream(file)) {
47              assertNotNull(stream.channel());
48          }
49      }
50  
51      @Test
52      public void testWrite() throws IOException {
53          final FileChannel channel = mock(FileChannel.class);
54          final FileRandomAccessOutputStream stream = new FileRandomAccessOutputStream(channel);
55          when(channel.write((ByteBuffer) any())).thenAnswer(answer -> {
56              ((ByteBuffer) answer.getArgument(0)).position(5);
57              return 5;
58          }).thenAnswer(answer -> {
59              ((ByteBuffer) answer.getArgument(0)).position(6);
60              return 6;
61          });
62          stream.write("hello".getBytes(StandardCharsets.UTF_8));
63          stream.write("world\n".getBytes(StandardCharsets.UTF_8));
64          verify(channel, times(2)).write((ByteBuffer) any());
65  
66          assertEquals(11, stream.position());
67      }
68  
69      @Test
70      public void testWriteFullyAt_whenFullAtOnce_thenSucceed() throws IOException {
71          final FileChannel channel = mock(FileChannel.class);
72          final FileRandomAccessOutputStream stream = new FileRandomAccessOutputStream(channel);
73          when(channel.write((ByteBuffer) any(), eq(20L))).thenAnswer(answer -> {
74              ((ByteBuffer) answer.getArgument(0)).position(5);
75              return 5;
76          });
77          when(channel.write((ByteBuffer) any(), eq(30L))).thenAnswer(answer -> {
78              ((ByteBuffer) answer.getArgument(0)).position(6);
79              return 6;
80          });
81          stream.writeFully("hello".getBytes(StandardCharsets.UTF_8), 20);
82          stream.writeFully("world\n".getBytes(StandardCharsets.UTF_8), 30);
83  
84          verify(channel, times(1)).write((ByteBuffer) any(), eq(20L));
85          verify(channel, times(1)).write((ByteBuffer) any(), eq(30L));
86  
87          assertEquals(0, stream.position());
88      }
89  
90      @Test
91      public void testWriteFullyAt_whenFullButPartial_thenSucceed() throws IOException {
92          final FileChannel channel = mock(FileChannel.class);
93          final FileRandomAccessOutputStream stream = new FileRandomAccessOutputStream(channel);
94          when(channel.write((ByteBuffer) any(), eq(20L))).thenAnswer(answer -> {
95              ((ByteBuffer) answer.getArgument(0)).position(3);
96              return 3;
97          });
98          when(channel.write((ByteBuffer) any(), eq(23L))).thenAnswer(answer -> {
99              ((ByteBuffer) answer.getArgument(0)).position(5);
100             return 2;
101         });
102         when(channel.write((ByteBuffer) any(), eq(30L))).thenAnswer(answer -> {
103             ((ByteBuffer) answer.getArgument(0)).position(6);
104             return 6;
105         });
106         stream.writeFully("hello".getBytes(StandardCharsets.UTF_8), 20);
107         stream.writeFully("world\n".getBytes(StandardCharsets.UTF_8), 30);
108 
109         verify(channel, times(1)).write((ByteBuffer) any(), eq(20L));
110         verify(channel, times(1)).write((ByteBuffer) any(), eq(23L));
111         verify(channel, times(1)).write((ByteBuffer) any(), eq(30L));
112 
113         assertEquals(0, stream.position());
114     }
115 
116     @Test
117     public void testWriteFullyAt_whenPartial_thenFail() throws IOException {
118         final FileChannel channel = mock(FileChannel.class);
119         final FileRandomAccessOutputStream stream = new FileRandomAccessOutputStream(channel);
120         when(channel.write((ByteBuffer) any(), eq(20L))).thenAnswer(answer -> {
121             ((ByteBuffer) answer.getArgument(0)).position(3);
122             return 3;
123         });
124         when(channel.write((ByteBuffer) any(), eq(23L))).thenAnswer(answer -> 0);
125         assertThrows(IOException.class, () -> stream.writeFully("hello".getBytes(StandardCharsets.UTF_8), 20));
126 
127         verify(channel, times(1)).write((ByteBuffer) any(), eq(20L));
128         verify(channel, times(1)).write((ByteBuffer) any(), eq(23L));
129         verify(channel, times(0)).write((ByteBuffer) any(), eq(25L));
130 
131         assertEquals(0, stream.position());
132     }
133 }