### Question:
AbstractClusterInvoker implements Invoker<T> { @Override public Result invoke(final Invocation invocation) throws RpcException { checkWhetherDestroyed(); Map<String, String> contextAttachments = RpcContext.getContext().getAttachments(); if (contextAttachments != null && contextAttachments.size() != 0) { ((RpcInvocation) invocation).addAttachments(contextAttachments); } List<Invoker<T>> invokers = list(invocation); LoadBalance loadbalance = initLoadBalance(invokers, invocation); RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation); return doInvoke(invocation, invokers, loadbalance); } AbstractClusterInvoker(Directory<T> directory);  AbstractClusterInvoker(Directory<T> directory, URL url); @Override Class<T> getInterface(); @Override URL getUrl(); @Override boolean isAvailable(); @Override void destroy(); @Override Result invoke(final Invocation invocation); @Override String toString();  }### Answer:
@Test public void testBindingAttachment() { final String attachKey = "attach"; final String attachValue = "value"; RpcContext.getContext().setAttachment(attachKey, attachValue); Map<String, String> attachments = RpcContext.getContext().getAttachments(); Assertions.assertTrue( attachments != null && attachments.size() == 1,"set attachment failed!"); cluster = new AbstractClusterInvoker(dic) { @Override protected Result doInvoke(Invocation invocation, List invokers, LoadBalance loadbalance) throws RpcException { String value = invocation.getAttachment(attachKey); Assertions.assertTrue(value != null && value.equals(attachValue),"binding attachment failed!"); return null; } }; cluster.invoke(invocation); }
@Test() public void testTimeoutExceptionCode() { List<Invoker<DemoService>> invokers = new ArrayList<Invoker<DemoService>>(); invokers.add(new Invoker<DemoService>() { @Override public Class<DemoService> getInterface() { return DemoService.class; } public URL getUrl() { return URL.valueOf("dubbo: } @Override public boolean isAvailable() { return false; } public Result invoke(Invocation invocation) throws RpcException { throw new RpcException(RpcException.TIMEOUT_EXCEPTION, "test timeout"); } @Override public void destroy() { } }); Directory<DemoService> directory = new StaticDirectory<DemoService>(invokers); FailoverClusterInvoker<DemoService> failoverClusterInvoker = new FailoverClusterInvoker<DemoService>(directory); try { failoverClusterInvoker.invoke(new RpcInvocation("sayHello", new Class<?>[0], new Object[0])); Assertions.fail(); } catch (RpcException e) { Assertions.assertEquals(RpcException.TIMEOUT_EXCEPTION, e.getCode()); } ForkingClusterInvoker<DemoService> forkingClusterInvoker = new ForkingClusterInvoker<DemoService>(directory); try { forkingClusterInvoker.invoke(new RpcInvocation("sayHello", new Class<?>[0], new Object[0])); Assertions.fail(); } catch (RpcException e) { Assertions.assertEquals(RpcException.TIMEOUT_EXCEPTION, e.getCode()); } FailfastClusterInvoker<DemoService> failfastClusterInvoker = new FailfastClusterInvoker<DemoService>(directory); try { failfastClusterInvoker.invoke(new RpcInvocation("sayHello", new Class<?>[0], new Object[0])); Assertions.fail(); } catch (RpcException e) { Assertions.assertEquals(RpcException.TIMEOUT_EXCEPTION, e.getCode()); } }