/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.hadoop.hdfs.storageservice.server; import com.facebook.nifty.client.FramedClientConnector; import com.facebook.swift.service.ThriftClientManager; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.permission.FsPermission; import org.apache.hadoop.hdfs.MiniAvatarCluster; import org.apache.hadoop.hdfs.protocol.ClientProxyProtocol; import org.apache.hadoop.hdfs.protocol.ClientProxyRequests.CreateRequest; import org.apache.hadoop.hdfs.protocol.ClientProxyRequests.GetPartialListingRequest; import org.apache.hadoop.hdfs.protocol.ClientProxyRequests.RequestMetaInfo; import org.apache.hadoop.hdfs.protocol.ClientProxyResponses.PartialListingResponse; import org.apache.hadoop.hdfs.protocol.FSConstants; import org.apache.hadoop.hdfs.protocol.HdfsFileStatus; import org.apache.hadoop.hdfs.protocol.TClientProxyProtocol; import org.apache.hadoop.hdfs.storageservice.StorageServiceConfigKeys; import org.apache.hadoop.hdfs.storageservice.server.ClientProxyService.ClientProxyCommons; import org.apache.hadoop.io.IOUtils; import org.apache.hadoop.ipc.RPC; import org.apache.hadoop.ipc.RemoteException; import org.apache.hadoop.security.UnixUserGroupInformation; import org.apache.hadoop.security.UserGroupInformation; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import java.io.IOException; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class TestClientProxyService { MiniAvatarCluster cluster; FileSystem fs; ClientProxyService proxy; ThriftClientManager clientManager; TClientProxyProtocol clientThrift; ClientProxyProtocol clientRPC; RequestMetaInfo metaInfo; @BeforeClass public static void setUpClass() throws Exception { MiniAvatarCluster.createAndStartZooKeeper(); } @Before public void setUp() throws Exception { try { Configuration conf = new Configuration(); // Bind ports automatically conf.setInt(StorageServiceConfigKeys.PROXY_THRIFT_PORT_KEY, 0); conf.setInt(StorageServiceConfigKeys.PROXY_RPC_PORT_KEY, 0); cluster = new MiniAvatarCluster(conf, 2, true, null, null, 1, true); fs = cluster.getFileSystem(0); metaInfo = new RequestMetaInfo(conf.getInt(FSConstants.DFS_CLUSTER_ID, RequestMetaInfo.NO_CLUSTER_ID), cluster.getNameNode(0).getNameserviceId(), RequestMetaInfo.NO_NAMESPACE_ID, RequestMetaInfo.NO_APPLICATION_ID, (UnixUserGroupInformation) UserGroupInformation.getUGI(conf)); proxy = new ClientProxyService(new ClientProxyCommons(conf, conf.get( FSConstants.DFS_CLUSTER_NAME))); conf.setInt(StorageServiceConfigKeys.PROXY_THRIFT_PORT_KEY, proxy.getThriftPort()); conf.setInt(StorageServiceConfigKeys.PROXY_RPC_PORT_KEY, proxy.getRPCPort()); clientManager = new ThriftClientManager(); FramedClientConnector connector = new FramedClientConnector( StorageServiceConfigKeys.getProxyThriftAddress(conf)); clientThrift = clientManager.createClient(connector, TClientProxyProtocol.class).get(); clientRPC = RPC.getProxy(ClientProxyProtocol.class, ClientProxyProtocol.versionID, StorageServiceConfigKeys.getProxyRPCAddress(conf), conf); } catch (IOException e) { tearDown(); throw e; } } @After public void tearDown() { RPC.stopProxy(clientRPC); IOUtils.cleanup(null, clientThrift, clientManager, proxy, fs); try { if (cluster != null) { cluster.shutDown(); } } catch (Exception e) { } } @AfterClass public static void tearDownClass() throws Exception { MiniAvatarCluster.shutDownZooKeeper(); } @TestImplementation(name = "create") public void create0(Path path) throws RemoteException { clientThrift.create(new CreateRequest(metaInfo, path.toString(), metaInfo.getOrigCaller().getUserName(), FsPermission.getDefault(), true, true, (short) 1, 1024)); } @TestImplementation(name = "create") public void create1(Path path) throws IOException { clientRPC.create(new CreateRequest(metaInfo, path.toString(), metaInfo.getOrigCaller().getUserName(), FsPermission.getDefault(), true, true, (short) 1, 1024)); } @Test public void testCreate() throws Exception { for (Method method : getTestImplementations("create", 2)) { Path path = new Path("/newfile"); assertFalse(fs.exists(path)); method.invoke(this, path); assertTrue(fs.exists(path)); fs.delete(path, true, true); } } @TestImplementation(name = "getPartialListing") public PartialListingResponse getPartialListing0(Path path) throws RemoteException { return clientThrift.getPartialListing(new GetPartialListingRequest(metaInfo, path.toString(), new byte[0])); } @TestImplementation(name = "getPartialListing") public PartialListingResponse getPartialListing1(Path path) throws IOException { return clientRPC.getPartialListing(new GetPartialListingRequest(metaInfo, path.toString(), new byte[0])); } @Test public void testGetPartialListing() throws Exception { for (Method method : getTestImplementations("getPartialListing", 2)) { Path path = new Path("/newdir/"); fs.mkdirs(path); for (int i = 0; i < 3; i++) { fs.create(new Path(path, "newfile" + i)); assertTrue(fs.exists(new Path(path, "newfile" + i))); } PartialListingResponse res = (PartialListingResponse) method.invoke(this, path); assertEquals(3, res.getListing().getFileStatusList().size()); int i = 0; for (HdfsFileStatus file : res.getListing().getFileStatusList()) { assertEquals("newfile" + i++, file.getLocalName()); } fs.delete(path, true, true); } } // TODO: more tests to come @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) private static @interface TestImplementation { public String name(); } private static Iterable<Method> getTestImplementations(String call, int count) { List<Method> subTests = new ArrayList<Method>(); for (Method method : TestClientProxyService.class.getMethods()) { TestImplementation annotation = method.getAnnotation(TestImplementation.class); if (annotation != null && annotation.name().matches(call + "[0-9]*")) { subTests.add(method); } } assertFalse("TestImplementations for call: " + call + " not found", subTests.isEmpty()); assertEquals("Wrong number of TestImplementations for call: " + call, count, subTests.size()); return subTests; } }