/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.portal.fabric.netty.fileserver.handlers; import com.liferay.portal.fabric.netty.codec.serialization.AnnotatedObjectDecoder; import com.liferay.portal.fabric.netty.fileserver.FileResponse; import com.liferay.portal.fabric.netty.util.NettyUtil; import com.liferay.portal.kernel.concurrent.AsyncBroker; import com.liferay.portal.kernel.concurrent.NoticeableFuture; import com.liferay.portal.kernel.test.CaptureHandler; import com.liferay.portal.kernel.test.JDKLoggerTestUtil; import com.liferay.portal.kernel.test.rule.CodeCoverageAssertor; import com.liferay.portal.kernel.util.Time; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPipeline; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.attribute.FileTime; import java.util.List; import java.util.concurrent.Future; import java.util.logging.Level; import java.util.logging.LogRecord; import org.junit.Assert; import org.junit.Before; import org.junit.ClassRule; import org.junit.Test; /** * @author Shuyang Zhou */ public class FileResponseChannelHandlerTest { @ClassRule public static final CodeCoverageAssertor codeCoverageAssertor = CodeCoverageAssertor.INSTANCE; @Before public void setUp() { _channelPipeline.addFirst(new AnnotatedObjectDecoder()); Channel channel = _channelPipeline.channel(); _fileResponseChannelHandler = new FileResponseChannelHandler( _asyncBroker, channel.eventLoop()); _channelPipeline.addFirst(_fileResponseChannelHandler); _channelHandlerContext = _channelPipeline.firstContext(); } @Test public void testFile() throws Exception { byte[] data = FileServerTestUtil.createRandomData(1024); long lastModified = FileServerTestUtil.getFileSystemTime( System.currentTimeMillis() - Time.DAY); FileResponse fileResponse = new FileResponse( _path, data.length, lastModified, false); NoticeableFuture<FileResponse> noticeableFuture = _asyncBroker.post( _path); _fileResponseChannelHandler.channelRead( _channelHandlerContext, fileResponse, FileServerTestUtil.wrapFirstHalf(data)); ChannelHandler channelHandler = _channelPipeline.first(); Assert.assertTrue(channelHandler instanceof FileUploadChannelHandler); FileUploadChannelHandler fileUploadChannelHandler = (FileUploadChannelHandler)channelHandler; _channelPipeline.fireChannelRead( FileServerTestUtil.wrapSecondHalf(data)); channelHandler = _channelPipeline.first(); Assert.assertFalse(channelHandler instanceof FileUploadChannelHandler); Assert.assertSame(fileResponse, fileUploadChannelHandler.fileResponse); Assert.assertSame(fileResponse, noticeableFuture.get()); Path localFile = fileResponse.getLocalFile(); Assert.assertNotNull(localFile); FileTime fileTime = Files.getLastModifiedTime(localFile); Assert.assertEquals(lastModified, fileTime.toMillis()); Assert.assertArrayEquals(data, Files.readAllBytes(localFile)); Files.delete(localFile); } @Test public void testFileNotFound() throws Exception { Future<FileResponse> future = _asyncBroker.post(_path); FileResponse fileResponse = new FileResponse( _path, FileResponse.FILE_NOT_FOUND, -1, false); _fileResponseChannelHandler.channelRead( _channelHandlerContext, fileResponse, null); Assert.assertSame(fileResponse, future.get()); } @Test public void testFileNotFoundNoMatchKey() throws Exception { FileResponse fileResponse = new FileResponse( _path, FileResponse.FILE_NOT_FOUND, -1, false); try (CaptureHandler captureHandler = JDKLoggerTestUtil.configureJDKLogger( FileResponseChannelHandler.class.getName(), Level.SEVERE)) { _fileResponseChannelHandler.channelRead( _channelHandlerContext, fileResponse, null); List<LogRecord> logRecords = captureHandler.getLogRecords(); Assert.assertEquals(logRecords.toString(), 1, logRecords.size()); LogRecord logRecord = logRecords.get(0); Assert.assertEquals( "Unable to place result " + fileResponse + " because no future exists with ID " + fileResponse.getPath(), logRecord.getMessage()); } } @Test public void testFileNotModified() throws Exception { Future<FileResponse> future = _asyncBroker.post(_path); FileResponse fileResponse = new FileResponse( _path, FileResponse.FILE_NOT_MODIFIED, -1, false); _fileResponseChannelHandler.channelRead( _channelHandlerContext, fileResponse, null); Assert.assertSame(fileResponse, future.get()); } @Test public void testFileNotModifiedNoMatchKey() throws Exception { FileResponse fileResponse = new FileResponse( _path, FileResponse.FILE_NOT_MODIFIED, -1, false); try (CaptureHandler captureHandler = JDKLoggerTestUtil.configureJDKLogger( FileResponseChannelHandler.class.getName(), Level.SEVERE)) { _fileResponseChannelHandler.channelRead( _channelHandlerContext, fileResponse, null); List<LogRecord> logRecords = captureHandler.getLogRecords(); Assert.assertEquals(logRecords.toString(), 1, logRecords.size()); LogRecord logRecord = logRecords.get(0); Assert.assertEquals( "Unable to place result " + fileResponse + " because no future exists with ID " + fileResponse.getPath(), logRecord.getMessage()); } } private static final Path _path = Paths.get("testFile"); private final AsyncBroker<Path, FileResponse> _asyncBroker = new AsyncBroker<>(); private ChannelHandlerContext _channelHandlerContext; private final ChannelPipeline _channelPipeline = NettyUtil.createEmptyChannelPipeline(); private FileResponseChannelHandler _fileResponseChannelHandler; }