diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index d7fa74e6b47..4cdde897926 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -600,14 +600,6 @@ - - - - - - - - diff --git a/rskj-core/build.gradle b/rskj-core/build.gradle index 60be93b5e61..8f56a34b171 100644 --- a/rskj-core/build.gradle +++ b/rskj-core/build.gradle @@ -73,7 +73,6 @@ ext { mapdbVer : '2.0-beta13', jsonrpc4jVer : '1.6', jaxwsRtVer : '2.3.5', - picocliVer : '4.6.3', bitcoinjThinVer: '0.14.4-rsk-14', rskjNativeVer: '1.3.0', @@ -95,7 +94,6 @@ ext { mapdbLib : "org.mapdb:mapdb:${libVersions.mapdbVer}", jsonrpc4jLib : "com.github.briandilley.jsonrpc4j:jsonrpc4j:${libVersions.jsonrpc4jVer}", jaxwsRtLib : "com.sun.xml.ws:jaxws-rt:${libVersions.jaxwsRtVer}", - picocliLib : "info.picocli:picocli:${libVersions.picocliVer}", bitcoinjThinLib : "co.rsk.bitcoinj:bitcoinj-thin:${libVersions.bitcoinjThinVer}", rskjNativeLib : "co.rsk:native:${libVersions.rskjNativeVer}", @@ -143,7 +141,6 @@ dependencies { implementation "${libs.mapdbLib}" implementation "${libs.jsonrpc4jLib}" implementation "${libs.jaxwsRtLib}" - implementation "${libs.picocliLib}" implementation "${libs.bitcoinjThinLib}" implementation "${libs.rskjNativeLib}" diff --git a/rskj-core/src/main/java/co/rsk/RskContext.java b/rskj-core/src/main/java/co/rsk/RskContext.java index 116b1982466..ba9beb15b90 100644 --- a/rskj-core/src/main/java/co/rsk/RskContext.java +++ b/rskj-core/src/main/java/co/rsk/RskContext.java @@ -258,14 +258,9 @@ public class RskContext implements NodeContext, NodeBootstrapper { /***** Constructors ***********************************************************************************************/ public RskContext(String[] args) { - this(args, false); - } - - public RskContext(String[] args, boolean ignoreUnmatchedArgs) { this(new CliArgs.Parser<>( NodeCliOptions.class, - NodeCliFlags.class, - ignoreUnmatchedArgs + NodeCliFlags.class ).parse(args)); } diff --git a/rskj-core/src/main/java/co/rsk/cli/CliArgs.java b/rskj-core/src/main/java/co/rsk/cli/CliArgs.java index 3452827f3a8..eb01fa4f693 100644 --- a/rskj-core/src/main/java/co/rsk/cli/CliArgs.java +++ b/rskj-core/src/main/java/co/rsk/cli/CliArgs.java @@ -77,16 +77,10 @@ public static class Parser & OptionalizableCliArg, F extends E private final EnumSet options; private final EnumSet flags; - private final boolean ignoreUnmatchedArgs; public Parser(Class optionsClass, Class flagsClass) { - this(optionsClass, flagsClass, false); - } - - public Parser(Class optionsClass, Class flagsClass, boolean ignoreUnmatchedArgs) { this.options = EnumSet.allOf(optionsClass); this.flags = EnumSet.allOf(flagsClass); - this.ignoreUnmatchedArgs = ignoreUnmatchedArgs; } public CliArgs parse(String[] args) { @@ -98,7 +92,27 @@ public CliArgs parse(String[] args) { for (int i = 0; i < args.length; i++) { switch (args[i].charAt(0)) { case '-': - this.parseArguments(args, i, options, flags, paramValueMap); + if (args[i].length() < 2) { + throw new IllegalArgumentException("You must provide an option name, e.g. -d"); + } + char currentChar = Character.toLowerCase(args[i].charAt(1)); + if (currentChar == '-') { + if (args[i].length() < 3) { + throw new IllegalArgumentException("You must provide a flag name, e.g. --quiet"); + } + flags.add(getFlagByName(args[i].substring(2, args[i].length()))); + } else if (currentChar == 'x') { + String arg = args[i].substring(2); + paramValueMap.putAll(parseArgToMap(arg)); + } else { + if (args.length - 1 == i) { + throw new IllegalArgumentException( + String.format("A value must be provided after the option -%s", args[i]) + ); + } + options.put(getOptionByName(args[i].substring(1, args[i].length())), args[i + 1]); + i++; + } break; default: arguments.add(args[i]); @@ -119,65 +133,22 @@ public CliArgs parse(String[] args) { return new CliArgs<>(arguments, options, flags, paramValueMap); } - private void parseArguments(String[] args, int i, Map options, Set flags, Map paramValueMap) { - if (args[i].length() < 2) { - throw new IllegalArgumentException("You must provide an option name, e.g. -d"); - } - char currentChar = Character.toLowerCase(args[i].charAt(1)); - if (currentChar == '-') { - if (args[i].length() < 3) { - throw new IllegalArgumentException("You must provide a flag name, e.g. --quiet"); - } - - F flag = getFlagByName(args[i].substring(2, args[i].length())); - - if (flag != null) { - flags.add(flag); - } - } else if (currentChar == 'x') { - String arg = args[i].substring(2); - paramValueMap.putAll(parseArgToMap(arg)); - } else { - if (args.length - 1 == i) { - throw new IllegalArgumentException( - String.format("A value must be provided after the option -%s", args[i]) - ); - } - - O option = getOptionByName(args[i].substring(1, args[i].length())); - - if (option != null) { - options.put(option, args[i + 1]); - } - - i++; - } - } - private F getFlagByName(String flagName) { - F flagFound = flags.stream() + return flags.stream() .filter(flag -> flag.getName().equals(flagName)) .findFirst() - .orElse(null); - - if (flagFound == null && !this.ignoreUnmatchedArgs) { - throw new NoSuchElementException(String.format("--%s is not a valid flag", flagName)); - } - - return flagFound; + .orElseThrow( + () -> new NoSuchElementException(String.format("--%s is not a valid flag", flagName)) + ); } private O getOptionByName(String optionName) { - O option = options.stream() + return options.stream() .filter(opt -> opt.getName().equals(optionName)) .findFirst() - .orElse(null); - - if (option == null && !this.ignoreUnmatchedArgs) { - throw new NoSuchElementException(String.format("-%s is not a valid option", optionName)); - } - - return option; + .orElseThrow( + () -> new NoSuchElementException(String.format("-%s is not a valid option", optionName)) + ); } /** diff --git a/rskj-core/src/main/java/co/rsk/cli/CliToolRskContextAware.java b/rskj-core/src/main/java/co/rsk/cli/CliToolRskContextAware.java index 5875b158f1d..e56b6841cfd 100644 --- a/rskj-core/src/main/java/co/rsk/cli/CliToolRskContextAware.java +++ b/rskj-core/src/main/java/co/rsk/cli/CliToolRskContextAware.java @@ -31,14 +31,12 @@ /** * An abstract class for cli tools that need {@link RskContext}. Lifecycle of the {@link RskContext} instance * is being managed by {@link CliToolRskContextAware}. - *

+ * * Also {@link CliToolRskContextAware} provides a logger instance for derived classes. */ public abstract class CliToolRskContextAware { private static final Logger logger = LoggerFactory.getLogger("clitool"); - protected RskContext ctx; - protected NodeStopper stopper; protected static CliToolRskContextAware create(@Nonnull Class cliToolClass) { Objects.requireNonNull(cliToolClass, "cliToolClass should not be null"); @@ -59,27 +57,18 @@ public void execute(@Nonnull String[] args) { execute(args, () -> new RskContext(args), System::exit); } - public void execute(@Nonnull String[] args, @Nonnull Factory contextFactory, @Nonnull NodeStopper nodeStopper) { + public void execute(@Nonnull String[] args, @Nonnull Factory contextFactory, @Nonnull NodeStopper stopper) { Objects.requireNonNull(args, "args should not be null"); Objects.requireNonNull(contextFactory, "contextFactory should not be null"); - Objects.requireNonNull(nodeStopper, "stopper should not be null"); + Objects.requireNonNull(stopper, "stopper should not be null"); String cliToolName = getClass().getSimpleName(); - // Ignore contextFactory if ctx was set previously - // in order to allow compatibility between picocli - // and old cli tool version - if (this.ctx == null) { - this.ctx = contextFactory.create(); - } - // Ignore nodeStopper if stopper was set previously - // in order to allow compatibility between picocli - // and old cli tool version - if (this.stopper == null) { - this.stopper = nodeStopper; - } - + RskContext ctx = null; + // not using try-with-resources because System::exit (from stopper) prevents autocloseable closing try { + ctx = contextFactory.create(); + printInfo("{} started", cliToolName); RskSystemProperties rskSystemProperties = ctx.getRskSystemProperties(); diff --git a/rskj-core/src/main/java/co/rsk/cli/PicoCliToolRskContextAware.java b/rskj-core/src/main/java/co/rsk/cli/PicoCliToolRskContextAware.java deleted file mode 100644 index 9ff608d451e..00000000000 --- a/rskj-core/src/main/java/co/rsk/cli/PicoCliToolRskContextAware.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * This file is part of RskJ - * Copyright (C) 2021 RSK Labs Ltd. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ -package co.rsk.cli; - -import co.rsk.RskContext; -import co.rsk.cli.exceptions.PicocliBadResultException; -import picocli.CommandLine; - -import javax.annotation.Nonnull; -import java.util.concurrent.Callable; - -public abstract class PicoCliToolRskContextAware extends CliToolRskContextAware implements Callable { - - @Override - protected void onExecute(@Nonnull String[] args, @Nonnull RskContext ctx) { - this.ctx = ctx; - - int result = new CommandLine(this).setUnmatchedArgumentsAllowed(true).execute(args); - - if (result != 0) { - throw new PicocliBadResultException(result); - } - } -} diff --git a/rskj-core/src/main/java/co/rsk/cli/exceptions/PicocliBadResultException.java b/rskj-core/src/main/java/co/rsk/cli/exceptions/PicocliBadResultException.java deleted file mode 100644 index d046f6d3237..00000000000 --- a/rskj-core/src/main/java/co/rsk/cli/exceptions/PicocliBadResultException.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This file is part of RskJ - * Copyright (C) 2017 RSK Labs Ltd. - * (derived from ethereumJ library, Copyright (c) 2016 ) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -package co.rsk.cli.exceptions; - -public class PicocliBadResultException extends RuntimeException { - private final int errorCode; - - public PicocliBadResultException(int errorCode) { - super(String.format("Command finished with code: %s", errorCode)); - - this.errorCode = errorCode; - } - - public int getErrorCode() { - return errorCode; - } -} diff --git a/rskj-core/src/main/java/co/rsk/cli/tools/ConnectBlocks.java b/rskj-core/src/main/java/co/rsk/cli/tools/ConnectBlocks.java index 8d81bfbaade..f8e63763fac 100644 --- a/rskj-core/src/main/java/co/rsk/cli/tools/ConnectBlocks.java +++ b/rskj-core/src/main/java/co/rsk/cli/tools/ConnectBlocks.java @@ -17,7 +17,8 @@ */ package co.rsk.cli.tools; -import co.rsk.cli.PicoCliToolRskContextAware; +import co.rsk.RskContext; +import co.rsk.cli.CliToolRskContextAware; import co.rsk.trie.TrieStore; import org.bouncycastle.util.encoders.Hex; import org.ethereum.core.Block; @@ -25,8 +26,8 @@ import org.ethereum.core.Blockchain; import org.ethereum.db.BlockStore; import org.ethereum.db.ReceiptStore; -import picocli.CommandLine; +import javax.annotation.Nonnull; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; @@ -39,36 +40,31 @@ * Required cli args: * - args[0] - file path */ -@CommandLine.Command(name = "connect-blocks", mixinStandardHelpOptions = true, version = "connect-blocks 1.0", - description = "Connects blocks to a chain from external source file") -public class ConnectBlocks extends PicoCliToolRskContextAware { - - @CommandLine.Option(names = {"-f", "--file"}, description = "Path to a file with blocks to connect", required = true) - private String filePath; +public class ConnectBlocks extends CliToolRskContextAware { public static void main(String[] args) throws IOException { create(MethodHandles.lookup().lookupClass()).execute(args); } @Override - public Integer call() throws IOException { + protected void onExecute(@Nonnull String[] args, @Nonnull RskContext ctx) throws Exception { BlockFactory blockFactory = ctx.getBlockFactory(); Blockchain blockchain = ctx.getBlockchain(); TrieStore trieStore = ctx.getTrieStore(); BlockStore blockStore = ctx.getBlockStore(); ReceiptStore receiptStore = ctx.getReceiptStore(); + String filename = args[0]; + long startTime = System.currentTimeMillis(); - try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) { + try (BufferedReader reader = new BufferedReader(new FileReader(filename))) { connectBlocks(blockFactory, blockchain, trieStore, blockStore, receiptStore, reader); } long endTime = System.currentTimeMillis(); printInfo("Duration: " + (endTime - startTime) + " millis"); - - return 0; } private void connectBlocks(BlockFactory blockFactory, Blockchain blockchain, TrieStore trieStore, BlockStore blockStore, ReceiptStore receiptStore, BufferedReader reader) throws IOException { diff --git a/rskj-core/src/main/java/co/rsk/cli/tools/DbMigrate.java b/rskj-core/src/main/java/co/rsk/cli/tools/DbMigrate.java index 694ff0093e5..81b113cd37e 100644 --- a/rskj-core/src/main/java/co/rsk/cli/tools/DbMigrate.java +++ b/rskj-core/src/main/java/co/rsk/cli/tools/DbMigrate.java @@ -17,15 +17,16 @@ */ package co.rsk.cli.tools; -import co.rsk.cli.PicoCliToolRskContextAware; +import co.rsk.RskContext; +import co.rsk.cli.CliToolRskContextAware; import org.ethereum.datasource.DataSourceKeyIterator; import org.ethereum.datasource.DbKind; import org.ethereum.datasource.KeyValueDataSource; import org.ethereum.util.FileUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import picocli.CommandLine; +import javax.annotation.Nonnull; import java.io.File; import java.io.IOException; import java.lang.invoke.MethodHandles; @@ -37,23 +38,18 @@ /** * The entry point for db migration CLI tool * This is an experimental/unsupported tool - * + *

* Required cli args: * - args[0] - database target where we are going to insert the information from the current selected database. - * + *

* We do support the migrations between the following databases: * - LevelDb (leveldb as argument) * - RocksDb (rocksdb as argument) */ -@CommandLine.Command(name = "db-migrate", mixinStandardHelpOptions = true, version = "db-migrate 1.0", - description = "Migrates between different databases such as leveldb and rocksdb.") -public class DbMigrate extends PicoCliToolRskContextAware { +public class DbMigrate extends CliToolRskContextAware { private static final Logger logger = LoggerFactory.getLogger(DbMigrate.class); private static final String NODE_ID_FILE = "nodeId.properties"; - @CommandLine.Option(names = {"-t", "--targetDb"}, description = "The target db to migrate to. Example: leveldb, rocksdb ...", required = true) - private String targetdb; - private static class DbInformation { private final KeyValueDataSource keyValueDataSource; private final String indexPath; @@ -95,19 +91,20 @@ public static void main(String[] args) { create(MethodHandles.lookup().lookupClass()).execute(args); } + @SuppressWarnings("unused") public DbMigrate() { } @Override - public Integer call() throws IOException { + protected void onExecute(@Nonnull String[] args, @Nonnull RskContext ctx) throws IOException { logger.info("Starting db migration..."); - if (this.targetdb == null) { + if (args.length == 0) { throw new IllegalArgumentException("Db to migrate not specified. Please specify in the first argument."); } DbKind sourceDbKind = ctx.getRskSystemProperties().databaseKind(); - DbKind targetDbKind = DbKind.ofName(this.targetdb); + DbKind targetDbKind = DbKind.ofName(args[0]); if (sourceDbKind == targetDbKind) { throw new IllegalArgumentException(String.format( @@ -142,8 +139,6 @@ public Integer call() throws IOException { FileUtil.recursiveDelete(sourceDbDir); Files.move(Paths.get(targetDbDir), Paths.get(sourceDbDir)); - - return 0; } private DbMigrationInformation buildDbMigrationInformation( diff --git a/rskj-core/src/main/java/co/rsk/cli/tools/ExecuteBlocks.java b/rskj-core/src/main/java/co/rsk/cli/tools/ExecuteBlocks.java index 2f80fafbed7..48b5c856995 100644 --- a/rskj-core/src/main/java/co/rsk/cli/tools/ExecuteBlocks.java +++ b/rskj-core/src/main/java/co/rsk/cli/tools/ExecuteBlocks.java @@ -17,7 +17,8 @@ */ package co.rsk.cli.tools; -import co.rsk.cli.PicoCliToolRskContextAware; +import co.rsk.RskContext; +import co.rsk.cli.CliToolRskContextAware; import co.rsk.core.bc.BlockExecutor; import co.rsk.core.bc.BlockResult; import co.rsk.crypto.Keccak256; @@ -25,9 +26,8 @@ import co.rsk.trie.TrieStore; import org.ethereum.core.Block; import org.ethereum.db.BlockStore; -import picocli.CommandLine; -import java.io.IOException; +import javax.annotation.Nonnull; import java.lang.invoke.MethodHandles; import java.util.Arrays; @@ -39,33 +39,27 @@ * - args[0] - from block number * - args[1] - to block number */ -@CommandLine.Command(name = "execute-blocks", mixinStandardHelpOptions = true, version = "execute-blocks 1.0", - description = "Executes blocks for a specified block range") -public class ExecuteBlocks extends PicoCliToolRskContextAware { - @CommandLine.Option(names = {"-fb", "--fromBlock"}, description = "From block number", required = true) - private Long fromBlockNumber; - - @CommandLine.Option(names = {"-tb", "--toBlock"}, description = "To block number", required = true) - private Long toBlockNumber; +public class ExecuteBlocks extends CliToolRskContextAware { public static void main(String[] args) { create(MethodHandles.lookup().lookupClass()).execute(args); } @Override - public Integer call() throws IOException { + protected void onExecute(@Nonnull String[] args, @Nonnull RskContext ctx) throws Exception { BlockExecutor blockExecutor = ctx.getBlockExecutor(); BlockStore blockStore = ctx.getBlockStore(); TrieStore trieStore = ctx.getTrieStore(); StateRootHandler stateRootHandler = ctx.getStateRootHandler(); - executeBlocks(blockExecutor, blockStore, trieStore, stateRootHandler); - - return 0; + executeBlocks(args, blockExecutor, blockStore, trieStore, stateRootHandler); } - private void executeBlocks(BlockExecutor blockExecutor, BlockStore blockStore, TrieStore trieStore, + private void executeBlocks(String[] args, BlockExecutor blockExecutor, BlockStore blockStore, TrieStore trieStore, StateRootHandler stateRootHandler) { + long fromBlockNumber = Long.parseLong(args[0]); + long toBlockNumber = Long.parseLong(args[1]); + for (long n = fromBlockNumber; n <= toBlockNumber; n++) { Block block = blockStore.getChainBlockByNumber(n); Block parent = blockStore.getBlockByHash(block.getParentHash().getBytes()); diff --git a/rskj-core/src/main/java/co/rsk/cli/tools/ExportBlocks.java b/rskj-core/src/main/java/co/rsk/cli/tools/ExportBlocks.java index 193de67574b..aa57637a328 100644 --- a/rskj-core/src/main/java/co/rsk/cli/tools/ExportBlocks.java +++ b/rskj-core/src/main/java/co/rsk/cli/tools/ExportBlocks.java @@ -17,16 +17,16 @@ */ package co.rsk.cli.tools; -import co.rsk.cli.PicoCliToolRskContextAware; +import co.rsk.RskContext; +import co.rsk.cli.CliToolRskContextAware; import co.rsk.core.BlockDifficulty; import org.ethereum.core.Block; import org.ethereum.db.BlockStore; import org.ethereum.util.ByteUtil; -import picocli.CommandLine; +import javax.annotation.Nonnull; import java.io.BufferedOutputStream; import java.io.FileOutputStream; -import java.io.IOException; import java.io.PrintStream; import java.lang.invoke.MethodHandles; @@ -39,34 +39,26 @@ * - args[1] - to block number * - args[2] - file path */ -@CommandLine.Command(name = "export-blocks", mixinStandardHelpOptions = true, version = "export-blocks 1.0", - description = "Exports blocks from a specific block range to a file") -public class ExportBlocks extends PicoCliToolRskContextAware { - @CommandLine.Option(names = {"-fb", "--fromBlock"}, description = "From block number", required = true) - private Long fromBlockNumber; - - @CommandLine.Option(names = {"-tb", "--toBlock"}, description = "To block number", required = true) - private Long toBlockNumber; - - @CommandLine.Option(names = {"-f", "--file"}, description = "Path to a file to export blocks to", required = true) - private String filePath; +public class ExportBlocks extends CliToolRskContextAware { public static void main(String[] args) { create(MethodHandles.lookup().lookupClass()).execute(args); } @Override - public Integer call() throws IOException { + protected void onExecute(@Nonnull String[] args, @Nonnull RskContext ctx) throws Exception { + String filePath = args[2]; BlockStore blockStore = ctx.getBlockStore(); try (PrintStream writer = new PrintStream(new BufferedOutputStream(new FileOutputStream(filePath)))) { - exportBlocks(blockStore, writer); + exportBlocks(args, blockStore, writer); } - - return 0; } - private void exportBlocks(BlockStore blockStore, PrintStream writer) { + private void exportBlocks(String[] args, BlockStore blockStore, PrintStream writer) { + long fromBlockNumber = Long.parseLong(args[0]); + long toBlockNumber = Long.parseLong(args[1]); + for (long n = fromBlockNumber; n <= toBlockNumber; n++) { Block block = blockStore.getChainBlockByNumber(n); BlockDifficulty totalDifficulty = blockStore.getTotalDifficultyForHash(block.getHash().getBytes()); diff --git a/rskj-core/src/main/java/co/rsk/cli/tools/ExportState.java b/rskj-core/src/main/java/co/rsk/cli/tools/ExportState.java index 7ad69f65fd2..c26ba19ea99 100644 --- a/rskj-core/src/main/java/co/rsk/cli/tools/ExportState.java +++ b/rskj-core/src/main/java/co/rsk/cli/tools/ExportState.java @@ -17,18 +17,18 @@ */ package co.rsk.cli.tools; -import co.rsk.cli.PicoCliToolRskContextAware; +import co.rsk.RskContext; +import co.rsk.cli.CliToolRskContextAware; import co.rsk.trie.NodeReference; import co.rsk.trie.Trie; import co.rsk.trie.TrieStore; import org.ethereum.core.Block; import org.ethereum.db.BlockStore; import org.ethereum.util.ByteUtil; -import picocli.CommandLine; +import javax.annotation.Nonnull; import java.io.BufferedOutputStream; import java.io.FileOutputStream; -import java.io.IOException; import java.io.PrintStream; import java.lang.invoke.MethodHandles; import java.util.Optional; @@ -41,32 +41,26 @@ * - args[0] - block number * - args[1] - file path */ -@CommandLine.Command(name = "export-state", mixinStandardHelpOptions = true, version = "export-state 1.0", - description = "Exports state at specific block number to a file") -public class ExportState extends PicoCliToolRskContextAware { - @CommandLine.Option(names = {"-b", "--block"}, description = "Block number", required = true) - private Long blockNumber; - - @CommandLine.Option(names = {"-f", "--file"}, description = "Path to a file to export state to", required = true) - private String filePath; +public class ExportState extends CliToolRskContextAware { public static void main(String[] args) { create(MethodHandles.lookup().lookupClass()).execute(args); } @Override - public Integer call() throws IOException { + protected void onExecute(@Nonnull String[] args, @Nonnull RskContext ctx) throws Exception { + String filePath = args[1]; BlockStore blockStore = ctx.getBlockStore(); TrieStore trieStore = ctx.getTrieStore(); try (PrintStream writer = new PrintStream(new BufferedOutputStream(new FileOutputStream(filePath)))) { - exportState(blockStore, trieStore, writer); + exportState(args, blockStore, trieStore, writer); } - - return 0; } - private void exportState(BlockStore blockStore, TrieStore trieStore, PrintStream writer) { + private void exportState(String[] args, BlockStore blockStore, TrieStore trieStore, PrintStream writer) { + long blockNumber = Long.parseLong(args[0]); + Block block = blockStore.getChainBlockByNumber(blockNumber); Optional otrie = trieStore.retrieve(block.getStateRoot()); diff --git a/rskj-core/src/main/java/co/rsk/cli/tools/GenerateOpenRpcDoc.java b/rskj-core/src/main/java/co/rsk/cli/tools/GenerateOpenRpcDoc.java index 361eead5059..95ca6ca306d 100644 --- a/rskj-core/src/main/java/co/rsk/cli/tools/GenerateOpenRpcDoc.java +++ b/rskj-core/src/main/java/co/rsk/cli/tools/GenerateOpenRpcDoc.java @@ -17,7 +17,6 @@ */ package co.rsk.cli.tools; -import co.rsk.cli.exceptions.PicocliBadResultException; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.databind.JavaType; @@ -26,10 +25,11 @@ import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.type.MapType; import com.fasterxml.jackson.databind.type.TypeFactory; +import com.google.common.annotations.VisibleForTesting; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import picocli.CommandLine; +import javax.annotation.Nonnull; import java.io.File; import java.io.IOException; import java.nio.file.Files; @@ -38,7 +38,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.Callable; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -58,9 +57,7 @@ *

  • args[2]: destination file containing the final OpenRPC json doc
  • * */ -@CommandLine.Command(name = "gen-rpc-docs", mixinStandardHelpOptions = true, version = "gen-rpc-docs 1.0", - description = "Generates OpenRPC json doc file by merging a static template with several json files under {workdir}/doc/rpc dir") -public class GenerateOpenRpcDoc implements Callable { +public class GenerateOpenRpcDoc { public static final JavaType TEMPLATE_DOC_TYPE = TypeFactory.defaultInstance().constructType(TemplateDoc.class); private static final JavaType OBJECT_TYPE = TypeFactory.defaultInstance().constructType(Object.class); @@ -68,41 +65,19 @@ public class GenerateOpenRpcDoc implements Callable { private static final Logger logger = LoggerFactory.getLogger(GenerateOpenRpcDoc.class); - @CommandLine.Option(names = {"-v", "--version"}, description = "RSKj version, will be present on final doc", required = true) - private String version; - - @CommandLine.Option(names = {"-d", "--dir"}, description = "work directory where the json template and individual json files are present", required = true) - private String dir; - - @CommandLine.Option(names = {"-o", "--outputFile"}, description = "destination file containing the final OpenRPC json doc", required = true) - private String outputFile; - protected static final ObjectMapper JSON_MAPPER = new ObjectMapper() .enable(SerializationFeature.INDENT_OUTPUT) .enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY); - public GenerateOpenRpcDoc() { - } - - public GenerateOpenRpcDoc(String version, String dir, String outputFile) { - this.version = version; - this.dir = dir; - this.outputFile = outputFile; - } - public static void main(String[] args) { - int result = new CommandLine(new GenerateOpenRpcDoc()).setUnmatchedArgumentsAllowed(true).execute(args); - - if (result != 0) { - throw new PicocliBadResultException(result); - } + new GenerateOpenRpcDoc().execute(args); } - @Override - public Integer call() { - String version = this.version; - String workDirPath = this.dir; - String destPath = this.outputFile; + @VisibleForTesting + void execute(@Nonnull String[] args) { + String version = args[0]; + String workDirPath = args[1]; + String destPath = args[2]; TemplateDoc templateDoc = loadTemplate(workDirPath); templateDoc.info.version = version; @@ -111,8 +86,6 @@ public Integer call() { templateDoc.components.contentDescriptors.putAll(loadContentDescriptors(workDirPath)); writeToFile(destPath, templateDoc); - - return 0; } private TemplateDoc loadTemplate(String workDirPath) { diff --git a/rskj-core/src/main/java/co/rsk/cli/tools/ImportBlocks.java b/rskj-core/src/main/java/co/rsk/cli/tools/ImportBlocks.java index 1176aaa0ae1..3dc742d9519 100644 --- a/rskj-core/src/main/java/co/rsk/cli/tools/ImportBlocks.java +++ b/rskj-core/src/main/java/co/rsk/cli/tools/ImportBlocks.java @@ -17,14 +17,15 @@ */ package co.rsk.cli.tools; -import co.rsk.cli.PicoCliToolRskContextAware; +import co.rsk.RskContext; +import co.rsk.cli.CliToolRskContextAware; import co.rsk.core.BlockDifficulty; import org.bouncycastle.util.encoders.Hex; import org.ethereum.core.Block; import org.ethereum.core.BlockFactory; import org.ethereum.db.BlockStore; -import picocli.CommandLine; +import javax.annotation.Nonnull; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; @@ -38,27 +39,22 @@ * Required cli args: * - args[0] - file path */ -@CommandLine.Command(name = "import-blocks", mixinStandardHelpOptions = true, version = "import-blocks 1.0", - description = "Imports blocks from a file") -public class ImportBlocks extends PicoCliToolRskContextAware { - - @CommandLine.Option(names = {"-f", "--file"}, description = "Path to a file to import blocks from", required = true) - private String filePath; +public class ImportBlocks extends CliToolRskContextAware { public static void main(String[] args) { create(MethodHandles.lookup().lookupClass()).execute(args); } @Override - public Integer call() throws IOException { + protected void onExecute(@Nonnull String[] args, @Nonnull RskContext ctx) throws Exception { BlockFactory blockFactory = ctx.getBlockFactory(); BlockStore blockStore = ctx.getBlockStore(); - try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) { + String filename = args[0]; + + try (BufferedReader reader = new BufferedReader(new FileReader(filename))) { importBlocks(blockFactory, blockStore, reader); } - - return 0; } private void importBlocks(BlockFactory blockFactory, BlockStore blockStore, BufferedReader reader) throws IOException { diff --git a/rskj-core/src/main/java/co/rsk/cli/tools/ImportState.java b/rskj-core/src/main/java/co/rsk/cli/tools/ImportState.java index b9a453ea864..bf283f89b9e 100644 --- a/rskj-core/src/main/java/co/rsk/cli/tools/ImportState.java +++ b/rskj-core/src/main/java/co/rsk/cli/tools/ImportState.java @@ -17,14 +17,15 @@ */ package co.rsk.cli.tools; -import co.rsk.cli.PicoCliToolRskContextAware; +import co.rsk.RskContext; +import co.rsk.cli.CliToolRskContextAware; import co.rsk.config.RskSystemProperties; import co.rsk.crypto.Keccak256; import org.bouncycastle.util.encoders.Hex; import org.ethereum.crypto.Keccak256Helper; import org.ethereum.datasource.KeyValueDataSource; -import picocli.CommandLine; +import javax.annotation.Nonnull; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; @@ -38,31 +39,26 @@ * Required cli args: * - args[0] - file path */ -@CommandLine.Command(name = "import-state", mixinStandardHelpOptions = true, version = "import-state 1.0", - description = "Imports state from a file") -public class ImportState extends PicoCliToolRskContextAware { - @CommandLine.Option(names = {"-f", "--file"}, description = "Path to a file to import state from", required = true) - private String filePath; - +public class ImportState extends CliToolRskContextAware { public static void main(String[] args) { create(MethodHandles.lookup().lookupClass()).execute(args); } @Override - public Integer call() throws IOException { + protected void onExecute(@Nonnull String[] args, @Nonnull RskContext ctx) throws Exception { RskSystemProperties rskSystemProperties = ctx.getRskSystemProperties(); String databaseDir = rskSystemProperties.databaseDir(); KeyValueDataSource trieDB = KeyValueDataSource.makeDataSource(Paths.get(databaseDir, "unitrie"), rskSystemProperties.databaseKind()); - try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) { + String filename = args[0]; + + try (BufferedReader reader = new BufferedReader(new FileReader(filename))) { importState(reader, trieDB); } trieDB.flush(); trieDB.close(); - - return 0; } private void importState(BufferedReader reader, KeyValueDataSource trieDB) throws IOException { diff --git a/rskj-core/src/main/java/co/rsk/cli/tools/IndexBlooms.java b/rskj-core/src/main/java/co/rsk/cli/tools/IndexBlooms.java index 96868e5def4..85e916e592a 100644 --- a/rskj-core/src/main/java/co/rsk/cli/tools/IndexBlooms.java +++ b/rskj-core/src/main/java/co/rsk/cli/tools/IndexBlooms.java @@ -18,7 +18,6 @@ package co.rsk.cli.tools; import co.rsk.RskContext; -import co.rsk.cli.exceptions.PicocliBadResultException; import co.rsk.logfilter.BlocksBloom; import co.rsk.logfilter.BlocksBloomStore; import org.ethereum.core.Block; @@ -26,71 +25,43 @@ import org.ethereum.db.BlockStore; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import picocli.CommandLine; import javax.annotation.Nonnull; -import java.io.IOException; -import java.util.concurrent.Callable; /** * The entry point for indexing block blooms * This is an experimental/unsupported tool */ -@CommandLine.Command(name = "index-blooms", mixinStandardHelpOptions = true, version = "index-blooms 1.0", - description = "Indexes blooms for a specific block range") -public class IndexBlooms implements Callable { - - @CommandLine.Option(names = {"-fb", "--fromBlock"}, description = "From block number", required = true) - private String fromBlockNumber; - - @CommandLine.Option(names = {"-tb", "--toBlock"}, description = "To block number", required = true) - private String toBlockNumber; +public class IndexBlooms { private static final Logger logger = LoggerFactory.getLogger(IndexBlooms.class); private static final String EARLIEST = "earliest"; private static final String LATEST = "latest"; - private final RskContext ctx; - - public IndexBlooms(RskContext ctx) { - this.ctx = ctx; - } - public static void main(String[] args) { - try (RskContext ctx = new RskContext(args, true)) { - int result = new CommandLine(new IndexBlooms(ctx)).setUnmatchedArgumentsAllowed(true).execute(args); + try (RskContext ctx = new RskContext(args)) { + BlockStore blockStore = ctx.getBlockStore(); + BlocksBloomStore blocksBloomStore = ctx.getBlocksBloomStore(); - if (result != 0) { - throw new PicocliBadResultException(result); - } + execute(makeBlockRange(args, blockStore), blockStore, blocksBloomStore); } } - @Override - public Integer call() throws IOException { - BlockStore blockStore = ctx.getBlockStore(); - BlocksBloomStore blocksBloomStore = ctx.getBlocksBloomStore(); - - execute(makeBlockRange(this.fromBlockNumber, this.toBlockNumber, blockStore), blockStore, blocksBloomStore); - - return 0; - } - /** * Creates a block range by extract from/to values from {@code args}. */ @Nonnull - static Range makeBlockRange(String fromBlock, String toBlock, @Nonnull BlockStore blockStore) { - if (fromBlock == null || toBlock == null) { + static Range makeBlockRange(@Nonnull String[] args, @Nonnull BlockStore blockStore) { + if (args.length < 2) { throw new IllegalArgumentException("Missing 'from' and/or 'to' block number(s)"); } long minNumber = blockStore.getMinNumber(); long maxNumber = blockStore.getMaxNumber(); - long fromBlockNumber = EARLIEST.equals(fromBlock) ? minNumber : Long.parseLong(fromBlock); - long toBlockNumber = LATEST.equals(toBlock) ? maxNumber : Long.parseLong(toBlock); + long fromBlockNumber = EARLIEST.equals(args[0]) ? minNumber : Long.parseLong(args[0]); + long toBlockNumber = LATEST.equals(args[1]) ? maxNumber : Long.parseLong(args[1]); if (fromBlockNumber < 0 || fromBlockNumber > toBlockNumber) { throw new IllegalArgumentException("Invalid 'from' and/or 'to' block number"); diff --git a/rskj-core/src/main/java/co/rsk/cli/tools/RewindBlocks.java b/rskj-core/src/main/java/co/rsk/cli/tools/RewindBlocks.java index c3284266ffe..dcf9abbe4d5 100644 --- a/rskj-core/src/main/java/co/rsk/cli/tools/RewindBlocks.java +++ b/rskj-core/src/main/java/co/rsk/cli/tools/RewindBlocks.java @@ -17,16 +17,15 @@ */ package co.rsk.cli.tools; -import co.rsk.cli.PicoCliToolRskContextAware; +import co.rsk.RskContext; +import co.rsk.cli.CliToolRskContextAware; import co.rsk.crypto.Keccak256; import co.rsk.db.RepositoryLocator; import com.google.common.annotations.VisibleForTesting; import org.ethereum.core.Block; import org.ethereum.db.BlockStore; -import picocli.CommandLine; import javax.annotation.Nonnull; -import java.io.IOException; import java.lang.invoke.MethodHandles; import java.util.Objects; import java.util.Optional; @@ -43,22 +42,7 @@ * - "fmi" option can be used for finding minimum inconsistent block number and printing it to stdout. It'll print -1, if no such block is found; * - "rbc" option does two things: it looks for minimum inconsistent block and, if there's such, rewinds blocks from top one till the found one inclusively. */ -@CommandLine.Command(name = "rewindblocks", mixinStandardHelpOptions = true, version = "rewindblocks 1.0", - description = "The entry point for rewind blocks state CLI tool") -public class RewindBlocks extends PicoCliToolRskContextAware { - static class RewindOpts { - @CommandLine.Option(names = {"-b", "--block"}, description = "block number to rewind blocks to") - public Long blockNum; - - @CommandLine.Option(names = {"-fmi", "--findMinInconsistentBlock"}, description = "flag to find a min inconsistent block", defaultValue = "false") - public Boolean findMinInconsistentBlock; - - @CommandLine.Option(names = {"-rbc", "--rewindToBestConsistentBlock"}, description = "flag to rewind to a best consistent block", defaultValue = "false") - public Boolean rewindToBestConsistentBlock; - } - - @CommandLine.ArgGroup(multiplicity = "1") - private RewindOpts opts; +public class RewindBlocks extends CliToolRskContextAware { public static void main(String[] args) { create(MethodHandles.lookup().lookupClass()).execute(args); @@ -77,22 +61,23 @@ public RewindBlocks() { // used via reflection } @Override - public Integer call() throws IOException { + protected void onExecute(@Nonnull String[] args, @Nonnull RskContext ctx) { BlockStore blockStore = ctx.getBlockStore(); + String blockNumOrOp = args[0]; - if (opts.findMinInconsistentBlock) { + if ("fmi".equals(blockNumOrOp)) { RepositoryLocator repositoryLocator = ctx.getRepositoryLocator(); printMinInconsistentBlock(blockStore, repositoryLocator); - } else if (opts.rewindToBestConsistentBlock) { + } else if ("rbc".equals(blockNumOrOp)) { RepositoryLocator repositoryLocator = ctx.getRepositoryLocator(); rewindInconsistentBlocks(blockStore, repositoryLocator); } else { - rewindBlocks(opts.blockNum, blockStore); - } + long blockNumber = Long.parseLong(blockNumOrOp); - return 0; + rewindBlocks(blockNumber, blockStore); + } } private void printMinInconsistentBlock(@Nonnull BlockStore blockStore, @Nonnull RepositoryLocator repositoryLocator) { diff --git a/rskj-core/src/main/java/co/rsk/cli/tools/ShowStateInfo.java b/rskj-core/src/main/java/co/rsk/cli/tools/ShowStateInfo.java index 55ca487f8bc..19d924f2e5a 100644 --- a/rskj-core/src/main/java/co/rsk/cli/tools/ShowStateInfo.java +++ b/rskj-core/src/main/java/co/rsk/cli/tools/ShowStateInfo.java @@ -17,7 +17,8 @@ */ package co.rsk.cli.tools; -import co.rsk.cli.PicoCliToolRskContextAware; +import co.rsk.RskContext; +import co.rsk.cli.CliToolRskContextAware; import co.rsk.trie.NodeReference; import co.rsk.trie.Trie; import co.rsk.trie.TrieStore; @@ -25,10 +26,8 @@ import org.ethereum.core.Block; import org.ethereum.db.BlockStore; import org.ethereum.util.ByteUtil; -import picocli.CommandLine; import javax.annotation.Nonnull; -import java.io.IOException; import java.lang.invoke.MethodHandles; import java.util.Objects; import java.util.Optional; @@ -40,12 +39,7 @@ * Required cli args: * - args[0] - block number or "best" */ -@CommandLine.Command(name = "show-state-info", mixinStandardHelpOptions = true, version = "show-state-info 1.0", - description = "Shows state information for a specific block number") -public class ShowStateInfo extends PicoCliToolRskContextAware { - - @CommandLine.Option(names = {"-b", "--block"}, description = "block number or \"best\"", required = true) - private String blockNum; +public class ShowStateInfo extends CliToolRskContextAware { public static void main(String[] args) { create(MethodHandles.lookup().lookupClass()).execute(args); @@ -64,25 +58,23 @@ public ShowStateInfo() { // used via reflection } @Override - public Integer call() throws IOException { + protected void onExecute(@Nonnull String[] args, @Nonnull RskContext ctx) throws Exception { BlockStore blockStore = ctx.getBlockStore(); TrieStore trieStore = ctx.getTrieStore(); - printStateInfo(blockStore, trieStore); - - return 0; + printStateInfo(args, blockStore, trieStore); } - private void printStateInfo(BlockStore blockStore, TrieStore trieStore) throws NumberFormatException { + private void printStateInfo(String[] args, BlockStore blockStore, TrieStore trieStore) { StateInfo stateInfo = new StateInfo(); Block block; - if ("best".equals(blockNum)) { + if ("best".equals(args[0])) { block = blockStore.getBestBlock(); } else { - block = blockStore.getChainBlockByNumber(Long.parseLong(blockNum)); + block = blockStore.getChainBlockByNumber(Long.parseLong(args[0])); } printer.println("Block number: " + block.getNumber()); diff --git a/rskj-core/src/main/java/co/rsk/cli/tools/StartBootstrap.java b/rskj-core/src/main/java/co/rsk/cli/tools/StartBootstrap.java index b2d93b0ca29..2c31b6f7842 100644 --- a/rskj-core/src/main/java/co/rsk/cli/tools/StartBootstrap.java +++ b/rskj-core/src/main/java/co/rsk/cli/tools/StartBootstrap.java @@ -19,7 +19,6 @@ import co.rsk.NodeRunner; import co.rsk.RskContext; -import co.rsk.cli.exceptions.PicocliBadResultException; import co.rsk.config.InternalService; import co.rsk.config.RskSystemProperties; import co.rsk.net.discovery.UDPServer; @@ -27,13 +26,10 @@ import co.rsk.util.PreflightChecksUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import picocli.CommandLine; import javax.annotation.Nonnull; -import java.io.IOException; import java.util.Collections; import java.util.List; -import java.util.concurrent.Callable; /** * Entry point of RSK bootstrap node. @@ -43,38 +39,19 @@ * * Note: this is an experimental tool */ -@CommandLine.Command(name = "start-bootstrap", mixinStandardHelpOptions = true, version = "start-bootstrap 1.0", - description = "Starts a bootstrap node with one service, which only participates in the peer discovery protocol") -public class StartBootstrap implements Callable { +public class StartBootstrap { private static final Logger logger = LoggerFactory.getLogger("bootstrap"); - private final RskContext ctx; - - public StartBootstrap(RskContext ctx) { - this.ctx = ctx; - } - public static void main(String[] args) { setUpThread(Thread.currentThread()); - try (RskContext ctx = new BootstrapRskContext(args)) { - int result = new CommandLine(new StartBootstrap(ctx)).setUnmatchedArgumentsAllowed(true).execute(args); - - if (result != 0) { - throw new PicocliBadResultException(result); - } - } - } - - @Override - public Integer call() throws IOException { + RskContext ctx = new BootstrapRskContext(args); PreflightChecksUtils preflightChecks = new PreflightChecksUtils(ctx); Runtime runtime = Runtime.getRuntime(); NodeStopper nodeStopper = System::exit; runBootstrapNode(ctx, preflightChecks, runtime, nodeStopper); - return 0; } static void runBootstrapNode(@Nonnull RskContext ctx, @@ -111,7 +88,7 @@ static void setUpThread(@Nonnull Thread thread) { static class BootstrapRskContext extends RskContext { BootstrapRskContext(String[] args) { - super(args, true); + super(args); } @Override diff --git a/rskj-core/src/test/java/co/rsk/cli/tools/CliToolsTest.java b/rskj-core/src/test/java/co/rsk/cli/tools/CliToolsTest.java index 8dccbb72358..e9fc458a7b9 100644 --- a/rskj-core/src/test/java/co/rsk/cli/tools/CliToolsTest.java +++ b/rskj-core/src/test/java/co/rsk/cli/tools/CliToolsTest.java @@ -19,7 +19,6 @@ import co.rsk.NodeRunner; import co.rsk.RskContext; -import co.rsk.cli.PicoCliToolRskContextAware; import co.rsk.config.RskSystemProperties; import co.rsk.config.TestSystemProperties; import co.rsk.core.BlockDifficulty; @@ -59,8 +58,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; -import picocli.CommandLine; import java.io.*; import java.nio.charset.StandardCharsets; @@ -92,7 +89,7 @@ void exportBlocks() throws IOException, DslProcessorException { processor.processCommands(parser); File blocksFile = tempDir.resolve( "blocks.txt").toFile(); - String[] args = new String[]{"--fromBlock", "0", "--toBlock", "2", "--file", blocksFile.getAbsolutePath()}; + String[] args = new String[]{"0", "2", blocksFile.getAbsolutePath()}; RskContext rskContext = mock(RskContext.class); RskSystemProperties rskSystemProperties = mock(RskSystemProperties.class); @@ -130,7 +127,7 @@ void exportState() throws IOException, DslProcessorException { processor.processCommands(parser); File stateFile = tempDir.resolve("state.txt").toFile(); - String[] args = new String[]{"--block", "2", "--file", stateFile.getAbsolutePath()}; + String[] args = new String[]{"2", stateFile.getAbsolutePath()}; RskContext rskContext = mock(RskContext.class); RskSystemProperties rskSystemProperties = mock(RskSystemProperties.class); @@ -170,7 +167,7 @@ void showStateInfo() throws FileNotFoundException, DslProcessorException { WorldDslProcessor processor = new WorldDslProcessor(world); processor.processCommands(parser); - String[] args = new String[]{"--block", "best"}; + String[] args = new String[]{"best"}; RskContext rskContext = mock(RskContext.class); RskSystemProperties rskSystemProperties = mock(RskSystemProperties.class); @@ -207,7 +204,7 @@ void executeBlocks() throws FileNotFoundException, DslProcessorException { WorldDslProcessor processor = new WorldDslProcessor(world); processor.processCommands(parser); - String[] args = new String[]{"--fromBlock", "1", "--toBlock", "2"}; + String[] args = new String[]{"1", "2"}; RskContext rskContext = mock(RskContext.class); RskSystemProperties rskSystemProperties = mock(RskSystemProperties.class); @@ -261,7 +258,7 @@ void connectBlocks() throws IOException, DslProcessorException { writer.write(stringBuilder.toString()); } - String[] args = new String[]{"--file", blocksFile.getAbsolutePath()}; + String[] args = new String[]{blocksFile.getAbsolutePath()}; RskContext rskContext = mock(RskContext.class); RskSystemProperties rskSystemProperties = mock(RskSystemProperties.class); @@ -318,7 +315,7 @@ void importBlocks() throws IOException, DslProcessorException { writer.write(stringBuilder.toString()); } - String[] args = new String[]{"--file", blocksFile.getAbsolutePath()}; + String[] args = new String[]{blocksFile.getAbsolutePath()}; RskContext rskContext = mock(RskContext.class); RskSystemProperties rskSystemProperties = mock(RskSystemProperties.class); @@ -354,7 +351,7 @@ void importState() throws IOException { } String databaseDir = tempDir.resolve( "db").toAbsolutePath().toString(); - String[] args = new String[]{"--file", stateFile.getAbsolutePath()}; + String[] args = new String[]{stateFile.getAbsolutePath()}; RskContext rskContext = mock(RskContext.class); RskSystemProperties rskSystemProperties = mock(RskSystemProperties.class); @@ -419,7 +416,7 @@ void rewindBlocks() { StringBuilder output = new StringBuilder(); RewindBlocks rewindBlocksCliTool = new RewindBlocks(output::append); - rewindBlocksCliTool.execute(new String[]{"-fmi"}, () -> rskContext, stopper); + rewindBlocksCliTool.execute(new String[]{"fmi"}, () -> rskContext, stopper); String data = output.toString(); Assertions.assertTrue(data.contains("No inconsistent block has been found")); @@ -432,7 +429,7 @@ void rewindBlocks() { output = new StringBuilder(); rewindBlocksCliTool = new RewindBlocks(output::append); - rewindBlocksCliTool.execute(new String[]{"--block", String.valueOf(blockToRewind)}, () -> rskContext, stopper); + rewindBlocksCliTool.execute(new String[]{String.valueOf(blockToRewind)}, () -> rskContext, stopper); bestBlock = indexedBlockStore.getBestBlock(); MatcherAssert.assertThat(bestBlock.getNumber(), is(blockToRewind)); @@ -446,7 +443,7 @@ void rewindBlocks() { output = new StringBuilder(); rewindBlocksCliTool = new RewindBlocks(output::append); - rewindBlocksCliTool.execute(new String[]{"--block", String.valueOf(blocksToGenerate + 1)}, () -> rskContext, stopper); + rewindBlocksCliTool.execute(new String[]{String.valueOf(blocksToGenerate + 1)}, () -> rskContext, stopper); bestBlock = indexedBlockStore.getBestBlock(); MatcherAssert.assertThat(bestBlock.getNumber(), is(blockToRewind)); @@ -462,7 +459,7 @@ void rewindBlocks() { output = new StringBuilder(); rewindBlocksCliTool = new RewindBlocks(output::append); - rewindBlocksCliTool.execute(new String[]{"-fmi"}, () -> rskContext, stopper); + rewindBlocksCliTool.execute(new String[]{"fmi"}, () -> rskContext, stopper); data = output.toString(); Assertions.assertTrue(data.contains("Min inconsistent block number: 0")); @@ -473,7 +470,7 @@ void rewindBlocks() { output = new StringBuilder(); rewindBlocksCliTool = new RewindBlocks(output::append); - rewindBlocksCliTool.execute(new String[]{"-rbc"}, () -> rskContext, stopper); + rewindBlocksCliTool.execute(new String[]{"rbc"}, () -> rskContext, stopper); data = output.toString(); Assertions.assertTrue(data.contains("Min inconsistent block number: 0")); @@ -506,7 +503,7 @@ void dbMigrate() throws IOException { NodeStopper stopper = mock(NodeStopper.class); DbMigrate dbMigrateCliTool = new DbMigrate(); - dbMigrateCliTool.execute(new String[]{"-t", "rocksdb"}, () -> rskContext, stopper); + dbMigrateCliTool.execute(new String[]{"rocksdb"}, () -> rskContext, stopper); String nodeIdPropsFileLine = null; @@ -577,29 +574,29 @@ void makeBlockRange() { doReturn(10L).when(blockStore).getMaxNumber(); try { - IndexBlooms.makeBlockRange(null, null, blockStore); + IndexBlooms.makeBlockRange(new String[]{}, blockStore); fail(); } catch (IllegalArgumentException ignored) { /* ignored */ } try { - IndexBlooms.makeBlockRange("0", null, blockStore); + IndexBlooms.makeBlockRange(new String[]{"0"}, blockStore); fail(); } catch (IllegalArgumentException ignored) { /* ignored */ } try { - IndexBlooms.makeBlockRange("0", "abc", blockStore); + IndexBlooms.makeBlockRange(new String[]{"0", "abc"}, blockStore); fail(); } catch (NumberFormatException ignored) { /* ignored */ } try { - IndexBlooms.makeBlockRange("-1", "1", blockStore); + IndexBlooms.makeBlockRange(new String[]{"-1", "1"}, blockStore); fail(); } catch (IllegalArgumentException e) { assertEquals("Invalid 'from' and/or 'to' block number", e.getMessage()); } try { - IndexBlooms.makeBlockRange("2", "1", blockStore); + IndexBlooms.makeBlockRange(new String[]{"2", "1"}, blockStore); fail(); } catch (IllegalArgumentException e) { assertEquals("Invalid 'from' and/or 'to' block number", e.getMessage()); @@ -608,20 +605,20 @@ void makeBlockRange() { doReturn(2L).when(blockStore).getMinNumber(); try { - IndexBlooms.makeBlockRange("1", "10", blockStore); // min block num is 10 + IndexBlooms.makeBlockRange(new String[]{"1", "10"}, blockStore); // min block num is 10 fail(); } catch (IllegalArgumentException e) { assertEquals("'from' block number is lesser than the min block number stored", e.getMessage()); } try { - IndexBlooms.makeBlockRange("5", "11", blockStore); // best block num is 10 + IndexBlooms.makeBlockRange(new String[]{"5", "11"}, blockStore); // best block num is 10 fail(); } catch (IllegalArgumentException e) { assertEquals("'to' block number is greater than the best block number", e.getMessage()); } - IndexBlooms.Range range = IndexBlooms.makeBlockRange("5", "10", blockStore); + IndexBlooms.Range range = IndexBlooms.makeBlockRange(new String[]{"5", "10"}, blockStore); assertEquals(5, range.fromBlockNumber); assertEquals(10, range.toBlockNumber); @@ -683,14 +680,12 @@ void generateOpenRpcDoc() throws IOException { File workDir = new File(classLoader.getResource("doc/rpc").getFile()); File destFile = tempDir.resolve( "generated_openrpc.json").toFile(); - GenerateOpenRpcDoc generateOpenRpcDocCliTool = new GenerateOpenRpcDoc( - version, - workDir.getAbsolutePath(), - destFile.getAbsolutePath() - ); + GenerateOpenRpcDoc generateOpenRpcDocCliTool = new GenerateOpenRpcDoc(); + + String[] args = new String[]{version, workDir.getAbsolutePath(), destFile.getAbsolutePath()}; try { - generateOpenRpcDocCliTool.call(); + generateOpenRpcDocCliTool.execute(args); } catch (RuntimeException e) { fail("should have not thrown " + e.getMessage()); } @@ -706,32 +701,4 @@ void generateOpenRpcDoc() throws IOException { assertEquals(expected, actual); } - - @Test - public void testErrorHandlingInPicocli() { - RskContext rskContext = mock(RskContext.class); - RskSystemProperties rskSystemProperties = mock(RskSystemProperties.class); - - doReturn(DbKind.LEVEL_DB).when(rskSystemProperties).databaseKind(); - doReturn(tempDir.getRoot().toFile().getPath()).when(rskSystemProperties).databaseDir(); - doReturn(true).when(rskSystemProperties).databaseReset(); - doReturn(rskSystemProperties).when(rskContext).getRskSystemProperties(); - - NodeStopper stopper = mock(NodeStopper.class); - - @CommandLine.Command(name = "dummy-tool", mixinStandardHelpOptions = true, version = "1.0", - description = "This is just a dummy tool") - class DummyCliTool extends PicoCliToolRskContextAware { - @Override - public Integer call() { - return -1; - } - } - - DummyCliTool dummyTool = new DummyCliTool(); - - dummyTool.execute(new String[]{}, () -> rskContext, stopper); - - verify(stopper, times(1)).stop(Mockito.eq(1)); - } }