content: /*
   * Copyright (C) 2010-2101 Alibaba Group Holding Limited.
   *
   * Licensed 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.alibaba.otter.shared.arbitrate.zookeeper;
  
  import java.io.IOException;
  import java.lang.reflect.Field;
  import java.net.InetSocketAddress;
  import java.util.Arrays;
  import java.util.List;
  import java.util.Locale;
  import java.util.concurrent.CountDownLatch;
  
  import mockit.Mock;
  import mockit.Mockit;
  
  import org.apache.zookeeper.ClientCnxn;
  import org.apache.zookeeper.KeeperException;
  import org.apache.zookeeper.WatchedEvent;
  import org.apache.zookeeper.Watcher;
  import org.apache.zookeeper.ZooKeeper;
  import org.apache.zookeeper.client.HostProvider;
  import org.apache.zookeeper.client.StaticHostProvider;
  import org.apache.zookeeper.data.Stat;
  import org.springframework.util.ReflectionUtils;
  import org.testng.annotations.BeforeClass;
  import org.testng.annotations.Test;
  
  import com.alibaba.otter.shared.arbitrate.BaseOtterTest;
  import com.alibaba.otter.shared.arbitrate.impl.manage.NodeSessionExpired;
  import com.alibaba.otter.shared.arbitrate.impl.zookeeper.ZooKeeperClient;
  import com.alibaba.otter.shared.common.utils.zookeeper.ZkClientx;
  import com.alibaba.otter.shared.common.utils.zookeeper.ZooKeeperx;
  
  /**
   * 测试下zookeeper优先集群列表
   * 
   * @author jianghang 2011-9-16 下午03:00:01
   * @version 4.0.0
   */
  public class ZooKeeperClientTest extends BaseOtterTest {
  
      private static final Field clientCnxnField      = ReflectionUtils.findField(ZooKeeper.class, "cnxn");
      private static final Field hostProviderField    = ReflectionUtils.findField(ClientCnxn.class, "hostProvider");
      private static final Field serverAddressesField = ReflectionUtils.findField(StaticHostProvider.class,
                                                          "serverAddresses");
      static {
          ReflectionUtils.makeAccessible(clientCnxnField);
          ReflectionUtils.makeAccessible(hostProviderField);
          ReflectionUtils.makeAccessible(serverAddressesField);
      }
  
      private String             cluster1             = "127.0.0.1:2188";
      private String             cluster2             = "127.0.0.1:2188,127.0.0.1:2188";
  
      // private String cluster1 = "127.0.0.1:2181";
      // private String cluster2 = "127.0.0.1:2181,127.0.0.1:2181";
  
      @BeforeClass
      public void initial() {
          String data = String.format(Locale.ENGLISH, "%010d", "268171150");
          System.out.println(data);
  
          Mockit.setUpMock(ZooKeeperClient.class, new Object() {
  
              @Mock
              private List<String> getServerAddrs() {
                  return Arrays.asList(cluster1, cluster2);
              }
  
          });
  
          // 初始化节点
          Mockit.setUpMock(NodeSessionExpired.class, new Object() {
  
              @Mock
              public void notification() {
                  return;
              }
  
          });
      }
  
      @Test
      public void testClient() {
          ZkClientx zk = ZooKeeperClient.getInstance();
          // 强制获取zk中的地址信息
          final ZooKeeper zkp = ((ZooKeeperx) zk.getConnection()).getZookeeper();
          ClientCnxn cnxn = (ClientCnxn) ReflectionUtils.getField(clientCnxnField, zkp);
          HostProvider hostProvider = (HostProvider) ReflectionUtils.getField(hostProviderField, cnxn);
          List<InetSocketAddress> serverAddrs = (List<InetSocketAddress>) ReflectionUtils.getField(serverAddressesField,
              hostProvider);
          want.number(serverAddrs.size()).isEqualTo(3);
          String s1 = serverAddrs.get(0).getAddress().getHostAddress() + ":" + serverAddrs.get(0).getPort();
          want.string(s1).isEqualTo(cluster1);
  
          Stat stat = new Stat();
          try {
              zkp.getChildren("/otter/channel/304/388", false, stat);
              System.out.println(stat.getCversion());
          } catch (KeeperException e2) {
              // TODO Auto-generated catch block
              e2.printStackTrace();
          } catch (InterruptedException e2) {
              // TODO Auto-generated catch block
              e2.printStackTrace();
          }
  
          // 测试下session timeout
          final CountDownLatch latch = new CountDownLatch(1);
          new Thread() {
  
              public void run() {
                  try {
                      zkp.getChildren("/", false);
                  } catch (KeeperException e1) {
                      want.fail();
                  } catch (InterruptedException e1) {
                      want.fail();
                  }
                  int sessionTimeout = zkp.getSessionTimeout();
                  long sessionId = zkp.getSessionId();
                  byte[] passwd = zkp.getSessionPasswd();
                  try {
                      ZooKeeper newZk = new ZooKeeper(cluster1, sessionTimeout, new Watcher() {
  
                          public void process(WatchedEvent event) {
                              // do nothing
                          }
  
                      }, sessionId, passwd);
  
                      // 用老的sessionId连接上去，进行一次close操作后，让原先正在使用的出现SESSION_EXPIRED
                      newZk.close();
                  } catch (IOException e) {
                      want.fail();
                  } catch (InterruptedException e) {
                      want.fail();
                  }
  
                  latch.countDown();
              }
  
          }.start();
  
          try {
              latch.await();
          } catch (InterruptedException e) {
              want.fail();
          }
  
          zk.getChildren("/");
      }
  }
  