/* * Copyright 2015 the original author or authors. * * 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 io.atomix.vertx; import java.io.File; import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.time.Duration; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.stream.IntStream; import io.atomix.cluster.Node; import io.atomix.cluster.discovery.BootstrapDiscoveryProvider; import io.atomix.cluster.protocol.SwimMembershipProtocol; import io.atomix.core.Atomix; import io.atomix.protocols.raft.partition.RaftPartitionGroup; import io.atomix.utils.net.Address; /** * Vert.x test helper. * * @author <a href="http://github.com/kuujo">Jordan Halterman</a> */ final class AtomixVertxTestHelper { private static final int BASE_PORT = 5000; private List<Atomix> instances; private int id = 10; void setUp() throws Exception { deleteData(); instances = new ArrayList<>(); instances.add(createAtomix(1, 1, 2, 3)); instances.add(createAtomix(2, 1, 2, 3)); instances.add(createAtomix(3, 1, 2, 3)); List<CompletableFuture<Void>> futures = instances.stream().map(Atomix::start).collect(Collectors.toList()); CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).get(30, TimeUnit.SECONDS); } /** * Creates an Atomix instance. */ private Atomix createAtomix(int id, int... ids) { Collection<Node> nodes = IntStream.of(ids) .mapToObj(memberId -> Node.builder() .withId(String.valueOf(memberId)) .withAddress(Address.from("localhost", BASE_PORT + memberId)) .build()) .collect(Collectors.toList()); return Atomix.builder() .withClusterId("test") .withMemberId(String.valueOf(id)) .withHost("localhost") .withPort(BASE_PORT + id) .withMembershipProtocol(SwimMembershipProtocol.builder() .withBroadcastDisputes(true) .withBroadcastUpdates(true) .withProbeInterval(Duration.ofMillis(100)) .withNotifySuspect(true) .withFailureTimeout(Duration.ofSeconds(3)) .build()) .withMembershipProvider(new BootstrapDiscoveryProvider(nodes)) .withManagementGroup(RaftPartitionGroup.builder("system") .withNumPartitions(1) .withPartitionSize(ids.length) .withMembers(nodes.stream().map(node -> node.id().id()).collect(Collectors.toSet())) .withDataDirectory(new File("target/test-logs/" + id + "/system")) .build()) .withPartitionGroups(RaftPartitionGroup.builder("test") .withNumPartitions(3) .withPartitionSize(ids.length) .withMembers(nodes.stream().map(node -> node.id().id()).collect(Collectors.toSet())) .withDataDirectory(new File("target/test-logs/" + id + "/test")) .build()) .build(); } /** * Returns the next Atomix cluster manager. * * @return The next Atomix cluster manager. */ AtomixClusterManager createClusterManager() { Atomix instance = createAtomix(id++, 1, 2, 3); instance.start().join(); instances.add(instance); return new AtomixClusterManager(instance); } void tearDown() throws Exception { List<CompletableFuture<Void>> futures = instances.stream().map(Atomix::stop).collect(Collectors.toList()); try { CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()])).join(); } catch (Exception e) { // Do nothing } deleteData(); } /** * Deletes data from the test data directory. */ private static void deleteData() throws Exception { Path directory = Paths.get("target/test-logs/"); if (Files.exists(directory)) { Files.walkFileTree(directory, new SimpleFileVisitor<Path>() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { Files.delete(file); return FileVisitResult.CONTINUE; } @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { Files.delete(dir); return FileVisitResult.CONTINUE; } }); } } }