/** * 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 com.twitter.distributedlog.metadata; import com.twitter.distributedlog.LocalDLMEmulator; import com.twitter.distributedlog.ZooKeeperClusterTestCase; import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.data.Stat; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.IOException; import java.net.URI; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; public class TestDLMetadata extends ZooKeeperClusterTestCase { private static final BKDLConfig bkdlConfig = new BKDLConfig("127.0.0.1:7000", "127.0.0.1:7000", "127.0.0.1:7000", "127.0.0.1:7000", "ledgers"); private static final BKDLConfig bkdlConfig2 = new BKDLConfig("127.0.0.1:7001", "127.0.0.1:7002", "127.0.0.1:7003", "127.0.0.1:7004", "ledgers2"); private ZooKeeper zkc; @Before public void setup() throws Exception { zkc = LocalDLMEmulator.connectZooKeeper("127.0.0.1", zkPort); } @After public void teardown() throws Exception { zkc.close(); } private URI createURI(String path) { return URI.create("distributedlog://127.0.0.1:" + zkPort + path); } @Test(timeout = 60000) public void testBadMetadata() throws Exception { URI uri = createURI("/"); try { DLMetadata.deserialize(uri, new byte[0]); fail("Should fail to deserialize invalid metadata"); } catch (IOException ie) { // expected } try { DLMetadata.deserialize(uri, new DLMetadata("unknown", bkdlConfig).serialize()); fail("Should fail to deserialize due to unknown dl type."); } catch (IOException ie) { // expected } try { DLMetadata.deserialize(uri, new DLMetadata(DLMetadata.BK_DL_TYPE, bkdlConfig, 9999).serialize()); fail("Should fail to deserialize due to invalid version."); } catch (IOException ie) { // expected } byte[] data = new DLMetadata(DLMetadata.BK_DL_TYPE, bkdlConfig).serialize(); // truncate data byte[] badData = new byte[data.length - 3]; System.arraycopy(data, 0, badData, 0, badData.length); try { DLMetadata.deserialize(uri, badData); fail("Should fail to deserialize truncated data."); } catch (IOException ie) { // expected } } @Test(timeout = 60000) public void testGoodMetadata() throws Exception { URI uri = createURI("/"); byte[] data = new DLMetadata(DLMetadata.BK_DL_TYPE, bkdlConfig).serialize(); DLMetadata deserailized = DLMetadata.deserialize(uri, data); assertEquals(bkdlConfig, deserailized.getDLConfig()); } @Test(timeout = 60000) public void testWriteMetadata() throws Exception { DLMetadata metadata = new DLMetadata(DLMetadata.BK_DL_TYPE, bkdlConfig); try { metadata.create(createURI("//metadata")); fail("Should fail due to invalid uri."); } catch (IllegalArgumentException e) { // expected } URI uri = createURI("/metadata"); metadata.create(uri); // create on existed path try { metadata.create(uri); fail("Should fail when create on existed path"); } catch (IOException e) { // expected } // update on unexisted path try { metadata.update(createURI("/unexisted")); fail("Should fail when update on unexisted path"); } catch (IOException e) { // expected } byte[] data = zkc.getData("/metadata", false, new Stat()); assertEquals(bkdlConfig, DLMetadata.deserialize(uri, data).getDLConfig()); // update on existed path DLMetadata newMetadata = new DLMetadata(DLMetadata.BK_DL_TYPE, bkdlConfig2); newMetadata.update(createURI("/metadata")); byte[] newData = zkc.getData("/metadata", false, new Stat()); assertEquals(bkdlConfig2, DLMetadata.deserialize(uri, newData).getDLConfig()); } // Missing dlZkServersForWriter, dlZkServersForReader default to configured server. @Test(timeout = 60000) public void testMetadataWithoutDLZKServers() throws Exception { testMetadataWithOrWithoutZkServers( "/metadata-without-dlzk-servers", null, null, "127.0.0.1:7003", "127.0.0.1:7004", "127.0.0.1:" + zkPort, "127.0.0.1:" + zkPort, "127.0.0.1:7003", "127.0.0.1:7004"); } @Test(timeout = 60000) public void testMetadataWithoutDLZKServersForRead() throws Exception { testMetadataWithOrWithoutZkServers( "/metadata-without-dlzk-servers-for-read", "127.0.0.1:7001", null, "127.0.0.1:7003", "127.0.0.1:7004", "127.0.0.1:7001", "127.0.0.1:7001", "127.0.0.1:7003", "127.0.0.1:7004"); } @Test(timeout = 60000) public void testMetadataWithoutBKZKServersForRead() throws Exception { testMetadataWithOrWithoutZkServers( "/metadata-without-bkzk-servers-for-read", "127.0.0.1:7001", null, "127.0.0.1:7003", null, "127.0.0.1:7001", "127.0.0.1:7001", "127.0.0.1:7003", "127.0.0.1:7003"); } private void testMetadataWithOrWithoutZkServers( String metadataPath, String dlZkServersForWriter, String dlZkServersForReader, String bkZkServersForWriter, String bkZkServersForReader, String expectedDlZkServersForWriter, String expectedDlZkServersForReader, String expectedBkZkServersForWriter, String expectedBkZkServersForReader ) throws Exception { BKDLConfig bkdlConfig = new BKDLConfig(dlZkServersForWriter, dlZkServersForReader, bkZkServersForWriter, bkZkServersForReader, "ledgers"); BKDLConfig expectedBKDLConfig = new BKDLConfig(expectedDlZkServersForWriter, expectedDlZkServersForReader, expectedBkZkServersForWriter, expectedBkZkServersForReader, "ledgers"); URI uri = createURI(metadataPath); DLMetadata metadata = new DLMetadata(DLMetadata.BK_DL_TYPE, bkdlConfig); metadata.create(uri); // read serialized metadata byte[] data = zkc.getData(metadataPath, false, new Stat()); assertEquals(expectedBKDLConfig, DLMetadata.deserialize(uri, data).getDLConfig()); } @Test(timeout = 60000) public void testMetadataMissingRequiredFields() throws Exception { BKDLConfig bkdlConfig = new BKDLConfig(null, null, null, null, "ledgers"); URI uri = createURI("/metadata-missing-fields"); DLMetadata metadata = new DLMetadata(DLMetadata.BK_DL_TYPE, bkdlConfig); metadata.create(uri); // read serialized metadata byte[] data = zkc.getData("/metadata-missing-fields", false, new Stat()); try { DLMetadata.deserialize(uri, data); fail("Should fail on deserializing metadata missing fields"); } catch (IOException ioe) { // expected } } }