diff options
author | Lukacs T. Berki <lberki@google.com> | 2017-04-18 14:13:49 +0200 |
---|---|---|
committer | Lukacs T. Berki <lberki@google.com> | 2017-04-18 14:15:05 +0200 |
commit | df8d804acb5826a120cad9acfc78dd6f0071d864 (patch) | |
tree | c15ca9e28ea15f66395fa1f8b1a069336a6b11b6 /third_party/java | |
parent | 50d62ee7888856f935d09e5fd60ee23d24d02b44 (diff) |
Vendor `jopt-simple 5.0.3` .
This is necessary for vendoring jarjar, which is in turn necessary to
get Java coverage collection to work again.
Yak shaving for #2820.
Change-Id: Idfd45e7322e0763fd316a4f67b1a048c93bf54ba
Diffstat (limited to 'third_party/java')
213 files changed, 20914 insertions, 0 deletions
diff --git a/third_party/java/jopt-simple/BUILD b/third_party/java/jopt-simple/BUILD new file mode 100644 index 0000000000..698edb34ff --- /dev/null +++ b/third_party/java/jopt-simple/BUILD @@ -0,0 +1,7 @@ +licenses(["notice"]) # MIT + +java_library( + name = "jopt-simple", + srcs = glob(["src/main/**/*.java"]), + visibility = ["//visibility:public"], +) diff --git a/third_party/java/jopt-simple/LICENSE.txt b/third_party/java/jopt-simple/LICENSE.txt new file mode 100644 index 0000000000..85f923a952 --- /dev/null +++ b/third_party/java/jopt-simple/LICENSE.txt @@ -0,0 +1,24 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ diff --git a/third_party/java/jopt-simple/README.bazel.md b/third_party/java/jopt-simple/README.bazel.md new file mode 100644 index 0000000000..9985e82975 --- /dev/null +++ b/third_party/java/jopt-simple/README.bazel.md @@ -0,0 +1,6 @@ +This is jopt-simple 5.0.3. Reproduction: + +1. `git clone https://github.com/jopt-simple/jopt-simple` +2. `git checkout jopt-simple-5.0.3` (commithash `b52b94611dba126a8236a10277d15676e31ab5f6`) +3. Dump the contents of the `git` tree into `third_party/java/jopt-simple` +4. Keep the existing, trivial `BUILD` file diff --git a/third_party/java/jopt-simple/README.md b/third_party/java/jopt-simple/README.md new file mode 100644 index 0000000000..ffe1ce208d --- /dev/null +++ b/third_party/java/jopt-simple/README.md @@ -0,0 +1,7 @@ +[![Build Status](https://travis-ci.org/pholser/jopt-simple.svg?branch=master)](https://travis-ci.org/pholser/jopt-simple) + +Please see http://pholser.github.com/jopt-simple for more information. + +### Discussing + +There is [a Google group for JOpt Simple](https://groups.google.com/d/forum/jopt-simple). diff --git a/third_party/java/jopt-simple/jopt-simple-eclipse-formatting.xml b/third_party/java/jopt-simple/jopt-simple-eclipse-formatting.xml new file mode 100644 index 0000000000..e4b2eb8312 --- /dev/null +++ b/third_party/java/jopt-simple/jopt-simple-eclipse-formatting.xml @@ -0,0 +1,283 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<profiles version="12"> +<profile kind="CodeFormatterProfile" name="jopt-simple" version="12"> +<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="false"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/> +<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/> +<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="16"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/> +<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="1"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/> +<setting id="org.eclipse.jdt.core.compiler.source" value="1.5"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/> +<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/> +<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/> +<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="16"/> +<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/> +<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/> +<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/> +<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/> +<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/> +<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="16"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/> +<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/> +<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/> +<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/> +<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/> +<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/> +<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/> +<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/> +<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.5"/> +<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="1"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/> +<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/> +<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/> +<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/> +<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/> +<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/> +<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/> +<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="120"/> +<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/> +<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/> +<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/> +<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/> +<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/> +<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/> +<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/> +<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/> +<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.5"/> +<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="16"/> +<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="true"/> +<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/> +<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="16"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/> +<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/> +<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/> +<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/> +<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/> +<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/> +<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/> +</profile> +</profiles> diff --git a/third_party/java/jopt-simple/jopt-simple.importorder b/third_party/java/jopt-simple/jopt-simple.importorder new file mode 100644 index 0000000000..e94bb816a3 --- /dev/null +++ b/third_party/java/jopt-simple/jopt-simple.importorder @@ -0,0 +1,8 @@ +#Organize Import Order +#Tue Oct 18 14:21:56 CDT 2011 +5=\# +4=\#javax +3=\#java +2= +1=javax +0=java diff --git a/third_party/java/jopt-simple/paste-examples.xml b/third_party/java/jopt-simple/paste-examples.xml new file mode 100644 index 0000000000..e1b6254481 --- /dev/null +++ b/third_party/java/jopt-simple/paste-examples.xml @@ -0,0 +1,205 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project> + <target name="-paste-examples"> + <filterchain id="htmlFilter"> + <filterreader + classname="joptsimple.examples.ant.filters.HTMLEntitifier" + classpath="${example.class.path}"/> + </filterchain> + <loadfile property="short.options.example" + srcfile="${example.src.dir}/joptsimple/examples/ShortOptionsTest.java"> + <filterchain refid="htmlFilter"/> + </loadfile> + <loadfile property="short.options.with.arguments.example" + srcfile="${example.src.dir}/joptsimple/examples/ShortOptionsWithArgumentsTest.java"> + <filterchain refid="htmlFilter"/> + </loadfile> + <loadfile property="short.options.with.argument.positioning.example" + srcfile="${example.src.dir}/joptsimple/examples/ShortOptionsWithArgumentPositioningTest.java"> + <filterchain refid="htmlFilter"/> + </loadfile> + <loadfile property="short.options.with.multiple.arguments.for.single.option.example" + srcfile="${example.src.dir}/joptsimple/examples/ShortOptionsWithMultipleArgumentsForSingleOptionTest.java"> + <filterchain refid="htmlFilter"/> + </loadfile> + <loadfile property="short.options.clustering.example" + srcfile="${example.src.dir}/joptsimple/examples/ShortOptionsClusteringTest.java"> + <filterchain refid="htmlFilter"/> + </loadfile> + <loadfile property="short.options.clustering.with.argument.example" + srcfile="${example.src.dir}/joptsimple/examples/ShortOptionsClusteringWithArgumentTest.java"> + <filterchain refid="htmlFilter"/> + </loadfile> + <loadfile property="long.options.example" + srcfile="${example.src.dir}/joptsimple/examples/LongOptionsTest.java"> + <filterchain refid="htmlFilter"/> + </loadfile> + <loadfile property="long.options.with.arguments.example" + srcfile="${example.src.dir}/joptsimple/examples/LongOptionsWithArgumentsTest.java"> + <filterchain refid="htmlFilter"/> + </loadfile> + <loadfile property="long.options.with.argument.positioning.example" + srcfile="${example.src.dir}/joptsimple/examples/LongOptionsWithArgumentPositioningTest.java"> + <filterchain refid="htmlFilter"/> + </loadfile> + <loadfile property="alternative.long.options.example" + srcfile="${example.src.dir}/joptsimple/examples/AlternativeLongOptionsTest.java"> + <filterchain refid="htmlFilter"/> + </loadfile> + <loadfile property="option.argument.value.type.example" + srcfile="${example.src.dir}/joptsimple/examples/OptionArgumentValueTypeTest.java"> + <filterchain refid="htmlFilter"/> + </loadfile> + <loadfile property="option.argument.converter.example" + srcfile="${example.src.dir}/joptsimple/examples/OptionArgumentConverterTest.java"> + <filterchain refid="htmlFilter"/> + </loadfile> + <loadfile property="typesafe.option.argument.retrieval.example" + srcfile="${example.src.dir}/joptsimple/examples/TypesafeOptionArgumentRetrievalTest.java"> + <filterchain refid="htmlFilter"/> + </loadfile> + <loadfile property="typesafe.option.argument.retrieval.example" + srcfile="${example.src.dir}/joptsimple/examples/TypesafeOptionArgumentRetrievalTest.java"> + <filterchain refid="htmlFilter"/> + </loadfile> + <loadfile property="export.options.example" + srcfile="${example.src.dir}/joptsimple/examples/ExportOptionsTest.java"> + <filterchain refid="htmlFilter"/> + </loadfile> + <loadfile property="required.options.example" + srcfile="${example.src.dir}/joptsimple/examples/RequiredOptionsTest.java"> + <filterchain refid="htmlFilter"/> + </loadfile> + <loadfile property="required.if.options.example" + srcfile="${example.src.dir}/joptsimple/examples/RequiredIfExample.java"> + <filterchain refid="htmlFilter"/> + </loadfile> + <loadfile property="required.unless.options.example" + srcfile="${example.src.dir}/joptsimple/examples/RequiredUnlessExample.java"> + <filterchain refid="htmlFilter"/> + </loadfile> + <loadfile property="default.values.for.option.arguments.example" + srcfile="${example.src.dir}/joptsimple/examples/DefaultValuesForOptionArgumentsTest.java"> + <filterchain refid="htmlFilter"/> + </loadfile> + <loadfile property="option.synonym.example" + srcfile="${example.src.dir}/joptsimple/examples/OptionSynonymTest.java"> + <filterchain refid="htmlFilter"/> + </loadfile> + <loadfile property="multiple.delimited.arguments.example" + srcfile="${example.src.dir}/joptsimple/examples/MultipleDelimitedArgumentsTest.java"> + <filterchain refid="htmlFilter"/> + </loadfile> + <loadfile property="signalling.end.of.options.example" + srcfile="${example.src.dir}/joptsimple/examples/SignallingEndOfOptionsTest.java"> + <filterchain refid="htmlFilter"/> + </loadfile> + <loadfile property="posixly.correct.example" + srcfile="${example.src.dir}/joptsimple/examples/PosixlyCorrectTest.java"> + <filterchain refid="htmlFilter"/> + </loadfile> + <loadfile property="special.optional.argument.handling.example" + srcfile="${example.src.dir}/joptsimple/examples/SpecialOptionalArgumentHandlingTest.java"> + <filterchain refid="htmlFilter"/> + </loadfile> + <loadfile property="help.screen.example" + srcfile="${example.src.dir}/joptsimple/examples/HelpScreenExample.java"> + <filterchain refid="htmlFilter"/> + </loadfile> + <java classname="joptsimple.examples.HelpScreenExample" + fork="yes" + output="${java.io.tmpdir}/help-output.txt" + classpath="${example.class.path}"> + </java> + <loadfile property="help.screen.example.help" + srcfile="${java.io.tmpdir}/help-output.txt"> + <filterchain refid="htmlFilter"/> + </loadfile> + <loadfile property="help.formatter.example" + srcfile="${example.src.dir}/joptsimple/examples/HelpFormatterExample.java"> + <filterchain refid="htmlFilter"/> + </loadfile> + <java classname="joptsimple.examples.HelpFormatterExample" + fork="yes" + output="${java.io.tmpdir}/help-formatter-output.txt" + classpath="${example.class.path}"> + </java> + <loadfile property="help.formatter.example.output" + srcfile="${java.io.tmpdir}/help-formatter-output.txt"> + <filterchain refid="htmlFilter"/> + </loadfile> + <java classname="joptsimple.examples.ExceptionExample" + fork="yes" + output="${java.io.tmpdir}/stack-trace-output.txt" + classpath="${example.class.path}"> + </java> + <loadfile property="example.stack.trace" + srcfile="${java.io.tmpdir}/stack-trace-output.txt"> + <filterchain refid="htmlFilter"/> + </loadfile> + <loadfile property="unrecognized.options.allowed.example" + srcfile="${example.src.dir}/joptsimple/examples/UnrecognizedOptionsAllowedTest.java"> + <filterchain refid="htmlFilter"/> + </loadfile> + <replace dir="${website.staging.dir}" includes="examples.html"> + <replacefilter token="@SHORT_OPTIONS_EXAMPLE@" + value="${short.options.example}"/> + <replacefilter token="@SHORT_OPTIONS_WITH_ARGUMENTS_EXAMPLE@" + value="${short.options.with.arguments.example}"/> + <replacefilter token="@SHORT_OPTIONS_WITH_ARGUMENT_POSITIONING_EXAMPLE@" + value="${short.options.with.argument.positioning.example}"/> + <replacefilter token="@SHORT_OPTIONS_WITH_MULTIPLE_ARGUMENTS_FOR_SINGLE_OPTION_EXAMPLE@" + value="${short.options.with.multiple.arguments.for.single.option.example}"/> + <replacefilter token="@SHORT_OPTIONS_CLUSTERING_EXAMPLE@" + value="${short.options.clustering.example}"/> + <replacefilter token="@SHORT_OPTIONS_CLUSTERING_WITH_ARGUMENT_EXAMPLE@" + value="${short.options.clustering.with.argument.example}" /> + <replacefilter token="@LONG_OPTIONS_EXAMPLE@" + value="${long.options.example}"/> + <replacefilter token="@LONG_OPTIONS_WITH_ARGUMENTS_EXAMPLE@" + value="${long.options.with.arguments.example}"/> + <replacefilter token="@LONG_OPTIONS_WITH_ARGUMENT_POSITIONING_EXAMPLE@" + value="${long.options.with.argument.positioning.example}"/> + <replacefilter token="@ALTERNATIVE_LONG_OPTIONS_EXAMPLE@" + value="${alternative.long.options.example}"/> + <replacefilter token="@OPTION_ARGUMENT_VALUE_TYPE_EXAMPLE@" + value="${option.argument.value.type.example}"/> + <replacefilter token="@OPTION_ARGUMENT_CONVERTER_EXAMPLE@" + value="${option.argument.converter.example}"/> + <replacefilter token="@TYPESAFE_OPTION_ARGUMENT_RETRIEVAL_EXAMPLE@" + value="${typesafe.option.argument.retrieval.example}"/> + <replacefilter token="@EXPORTING_OPTIONS_AND_ARGUMENTS_EXAMPLE@" + value="${export.options.example}"/> + <replacefilter token="@DEFAULT_VALUES_FOR_OPTION_ARGUMENTS_EXAMPLE@" + value="${default.values.for.option.arguments.example}"/> + <replacefilter token="@REQUIRED_OPTIONS_EXAMPLE@" + value="${required.options.example}"/> + <replacefilter token="@REQUIRED_IF_OPTIONS_EXAMPLE@" + value="${required.if.options.example}"/> + <replacefilter token="@REQUIRED_UNLESS_OPTIONS_EXAMPLE@" + value="${required.unless.options.example}"/> + <replacefilter token="@OPTION_SYNONYM_EXAMPLE@" + value="${option.synonym.example}"/> + <replacefilter token="@MULTIPLE_DELIMITED_ARGUMENTS_EXAMPLE@" + value="${multiple.delimited.arguments.example}"/> + <replacefilter token="@SIGNALLING_END_OF_OPTIONS_EXAMPLE@" + value="${signalling.end.of.options.example}"/> + <replacefilter token="@POSIXLY_CORRECT_EXAMPLE@" + value="${posixly.correct.example}"/> + <replacefilter token="@SPECIAL_OPTIONAL_ARGUMENT_HANDLING_EXAMPLE@" + value="${special.optional.argument.handling.example}"/> + <replacefilter token="@HELP_SCREEN_EXAMPLE@" + value="${help.screen.example}"/> + <replacefilter token="@HELP_SCREEN_EXAMPLE_HELP@" + value="${help.screen.example.help}"/> + <replacefilter token="@HELP_FORMATTER_EXAMPLE@" + value="${help.formatter.example}"/> + <replacefilter token="@HELP_FORMATTER_EXAMPLE_OUTPUT@" + value="${help.formatter.example.output}"/> + <replacefilter token="@EXAMPLE_STACK_TRACE@" + value="${example.stack.trace}"/> + <replacefilter token="@UNRECOGNIZED_OPTIONS_ALLOWED_EXAMPLE@" + value="${unrecognized.options.allowed.example}"/> + </replace> + </target> +</project> diff --git a/third_party/java/jopt-simple/pom.xml b/third_party/java/jopt-simple/pom.xml new file mode 100644 index 0000000000..c2fc280944 --- /dev/null +++ b/third_party/java/jopt-simple/pom.xml @@ -0,0 +1,342 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.sonatype.oss</groupId> + <artifactId>oss-parent</artifactId> + <version>7</version> + </parent> + <groupId>net.sf.jopt-simple</groupId> + <artifactId>jopt-simple</artifactId> + <version>5.0.3</version> + <packaging>jar</packaging> + <name>JOpt Simple</name> + <url>http://pholser.github.io/jopt-simple</url> + <description>A Java library for parsing command line options</description> + <licenses> + <license> + <name>The MIT License</name> + <url>http://www.opensource.org/licenses/mit-license.php</url> + <distribution>repo</distribution> + </license> + </licenses> + <scm> + <connection>scm:git:git://github.com/pholser/jopt-simple.git</connection> + <developerConnection>scm:git:ssh://git@github.com/pholser/jopt-simple.git</developerConnection> + <url>https://github.com/pholser/jopt-simple</url> + </scm> + <issueManagement> + <system>GitHub</system> + <url>https://github.com/pholser/jopt-simple/issues</url> + </issueManagement> + <developers> + <developer> + <id>pholser</id> + <name>Paul Holser</name> + <email>pholser@alumni.rice.edu</email> + <url>http://www.pholser.com</url> + </developer> + </developers> + <properties> + <project.build.outputEncoding>UTF-8</project.build.outputEncoding> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <project.project.outputEncoding>UTF-8</project.project.outputEncoding> + </properties> + <dependencies> + <dependency> + <groupId>joda-time</groupId> + <artifactId>joda-time</artifactId> + <version>2.3</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.ant</groupId> + <artifactId>ant</artifactId> + <version>1.8.4</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>hamcrest-all</artifactId> + <version>1.3</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.12</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.infinitest</groupId> + <artifactId>continuous-testing-toolkit</artifactId> + <version>1.0</version> + <scope>test</scope> + <exclusions> + <exclusion> + <groupId>org.hamcrest</groupId> + <artifactId>hamcrest-all</artifactId> + </exclusion> + </exclusions> + </dependency> + </dependencies> + <build> + <extensions> + <extension> + <groupId>org.apache.maven.scm</groupId> + <artifactId>maven-scm-provider-gitexe</artifactId> + <version>1.9.2</version> + </extension> + <extension> + <groupId>org.apache.maven.scm</groupId> + <artifactId>maven-scm-manager-plexus</artifactId> + <version>1.9.2</version> + </extension> + <extension> + <groupId>org.kathrynhuxtable.maven.wagon</groupId> + <artifactId>wagon-gitsite</artifactId> + <version>0.3.1</version> + </extension> + </extensions> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.2</version> + <configuration> + <source>1.7</source> + <target>1.7</target> + </configuration> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>animal-sniffer-maven-plugin</artifactId> + <version>1.13</version> + <configuration> + <signature> + <groupId>org.codehaus.mojo.signature</groupId> + <artifactId>java17</artifactId> + <version>1.0</version> + </signature> + </configuration> + <executions> + <execution> + <id>check-signature</id> + <goals> + <goal>check</goal> + </goals> + </execution> + <!-- Needs updated version of animal sniffer plugin + <execution> + <id>check-test-signature</id> + <goals> + <goal>test-check</goal> + </goals> + </execution> + --> + </executions> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <version>2.3.7</version> + <extensions>true</extensions> + <configuration> + <instructions> + <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName> + <Bundle-Name>${project.artifactId}</Bundle-Name> + <Bundle-Version>${project.version}</Bundle-Version> + <Bundle-Vendor>${project.name}</Bundle-Vendor> + <Export-Package>joptsimple,joptsimple.util</Export-Package> + <Private-Package>joptsimple.internal</Private-Package> + </instructions> + </configuration> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>bundle</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>cobertura-maven-plugin</artifactId> + <version>2.6</version> + <configuration> + <check> + <haltOnFailure>true</haltOnFailure> + <totalBranchRate>96</totalBranchRate> + <totalLineRate>99</totalLineRate> + </check> + </configuration> + <executions> + <execution> + <goals> + <goal>clean</goal> + <goal>check</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-pmd-plugin</artifactId> + <version>3.4</version> + <configuration> + <minimumTokens>40</minimumTokens> + <targetJdk>1.7</targetJdk> + </configuration> + <executions> + <execution> + <phase>compile</phase> + <goals> + <goal>cpd-check</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-antrun-plugin</artifactId> + <version>1.8</version> + <executions> + <execution> + <id>paste-examples</id> + <phase>post-site</phase> + <configuration> + <target> + <property name="java.io.tmpdir" value="${java.io.tmpdir}" /> + <property name="example.src.dir" value="src/test/java" /> + <property name="example.class.path" refid="maven.test.classpath" /> + <property name="website.staging.dir" value="${project.build.directory}/site" /> + <ant antfile="paste-examples.xml" target="-paste-examples" /> + </target> + </configuration> + <goals> + <goal>run</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-site-plugin</artifactId> + <version>3.3</version> + <configuration> + <outputEncoding>UTF-8</outputEncoding> + </configuration> + </plugin> + <plugin> + <groupId>org.pitest</groupId> + <artifactId>pitest-maven</artifactId> + <version>1.1.9</version> + <configuration> + <targetClasses> + <param>joptsimple*</param> + </targetClasses> + <targetTests> + <param>*Test</param> + </targetTests> + <excludedMethods> + <param>equals</param> + <param>hashCode</param> + </excludedMethods> + <excludedClasses> + <param>joptsimple.examples*</param> + <param>*EqualsHash*Test</param> + <param>*TestCase</param> + <param>*Fixture</param> + <param>*Harness</param> + <param>*Matchers</param> + <param>*Ctor</param> + <param>*Problematic</param> + <param>*ValueOfHaver</param> + </excludedClasses> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-source-plugin</artifactId> + <version>2.4</version> + <executions> + <execution> + <id>attach-sources</id> + <phase>package</phase> + <goals> + <goal>jar</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + <reporting> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-project-info-reports-plugin</artifactId> + <version>2.8</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <version>2.9.1</version> + <configuration> + <source>1.7</source> + <show>public</show> + <excludePackageNames>joptsimple.examples:joptsimple.internal:joptsimple.internal.*</excludePackageNames> + <links> + <link>https://docs.oracle.com/javase/8/docs/api</link> + </links> + <bottom><![CDATA[<i>© Copyright 2004-2015 Paul R. Holser, Jr. All rights reserved. Licensed under The MIT License. pholser@alumni.rice.edu</i>]]></bottom> + </configuration> + <reportSets> + <reportSet> + <reports> + <report>javadoc</report> + </reports> + </reportSet> + </reportSets> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>cobertura-maven-plugin</artifactId> + <version>2.6</version> + <configuration> + <check> + <haltOnFailure>true</haltOnFailure> + <totalBranchRate>97</totalBranchRate> + <totalLineRate>99</totalLineRate> + </check> + <formats> + <format>xml</format> + <format>html</format> + </formats> + </configuration> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>findbugs-maven-plugin</artifactId> + <version>3.0.0</version> + <configuration> + <threshold>Low</threshold> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-pmd-plugin</artifactId> + <version>3.4</version> + <configuration> + <minimumTokens>40</minimumTokens> + <targetJdk>1.7</targetJdk> + </configuration> + </plugin> + </plugins> + </reporting> + <distributionManagement> + <site> + <id>github-project-site</id> + <url>gitsite:git@github.com/pholser/jopt-simple.git</url> + </site> + </distributionManagement> +</project> diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/AbstractOptionSpec.java b/third_party/java/jopt-simple/src/main/java/joptsimple/AbstractOptionSpec.java new file mode 100644 index 0000000000..2c045bd500 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/AbstractOptionSpec.java @@ -0,0 +1,148 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.ArrayList; +import java.util.List; + +import static java.util.Collections.*; + +import joptsimple.internal.Reflection; +import joptsimple.internal.ReflectionException; + +import static joptsimple.internal.Strings.*; + +/** + * @param <V> represents the type of the arguments this option accepts + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public abstract class AbstractOptionSpec<V> implements OptionSpec<V>, OptionDescriptor { + private final List<String> options = new ArrayList<>(); + private final String description; + private boolean forHelp; + + AbstractOptionSpec( String option ) { + this( singletonList( option ), EMPTY ); + } + + AbstractOptionSpec( List<String> options, String description ) { + arrangeOptions( options ); + + this.description = description; + } + + public final List<String> options() { + return unmodifiableList( options ); + } + + public final List<V> values( OptionSet detectedOptions ) { + return detectedOptions.valuesOf( this ); + } + + public final V value( OptionSet detectedOptions ) { + return detectedOptions.valueOf( this ); + } + + public String description() { + return description; + } + + public final AbstractOptionSpec<V> forHelp() { + forHelp = true; + return this; + } + + public final boolean isForHelp() { + return forHelp; + } + + public boolean representsNonOptions() { + return false; + } + + protected abstract V convert( String argument ); + + protected V convertWith( ValueConverter<V> converter, String argument ) { + try { + return Reflection.convertWith( converter, argument ); + } catch ( ReflectionException | ValueConversionException ex ) { + throw new OptionArgumentConversionException( this, argument, ex ); + } + } + + protected String argumentTypeIndicatorFrom( ValueConverter<V> converter ) { + if ( converter == null ) + return null; + + String pattern = converter.valuePattern(); + return pattern == null ? converter.valueType().getName() : pattern; + } + + abstract void handleOption( OptionParser parser, ArgumentList arguments, OptionSet detectedOptions, + String detectedArgument ); + + private void arrangeOptions( List<String> unarranged ) { + if ( unarranged.size() == 1 ) { + options.addAll( unarranged ); + return; + } + + List<String> shortOptions = new ArrayList<>(); + List<String> longOptions = new ArrayList<>(); + + for ( String each : unarranged ) { + if ( each.length() == 1 ) + shortOptions.add( each ); + else + longOptions.add( each ); + } + + sort( shortOptions ); + sort( longOptions ); + + options.addAll( shortOptions ); + options.addAll( longOptions ); + } + + @Override + public boolean equals( Object that ) { + if ( !( that instanceof AbstractOptionSpec<?> ) ) + return false; + + AbstractOptionSpec<?> other = (AbstractOptionSpec<?>) that; + return options.equals( other.options ); + } + + @Override + public int hashCode() { + return options.hashCode(); + } + + @Override + public String toString() { + return options.toString(); + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/AlternativeLongOptionSpec.java b/third_party/java/jopt-simple/src/main/java/joptsimple/AlternativeLongOptionSpec.java new file mode 100644 index 0000000000..a3108c1da4 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/AlternativeLongOptionSpec.java @@ -0,0 +1,65 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import joptsimple.internal.Messages; + +import java.util.Locale; + +import static java.util.Collections.*; + +import static joptsimple.ParserRules.*; + +/** + * Represents the {@code "-W"} form of long option specification. + * + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +class AlternativeLongOptionSpec extends ArgumentAcceptingOptionSpec<String> { + AlternativeLongOptionSpec() { + super( singletonList( RESERVED_FOR_EXTENSIONS ), + true, + Messages.message( + Locale.getDefault(), + "joptsimple.HelpFormatterMessages", + AlternativeLongOptionSpec.class, + "description" ) ); + + describedAs( Messages.message( + Locale.getDefault(), + "joptsimple.HelpFormatterMessages", + AlternativeLongOptionSpec.class, + "arg.description" ) ); + } + + @Override + protected void detectOptionArgument( OptionParser parser, ArgumentList arguments, OptionSet detectedOptions ) { + if ( !arguments.hasMore() ) + throw new OptionMissingRequiredArgumentException( this ); + + arguments.treatNextAsLongOption(); + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/ArgumentAcceptingOptionSpec.java b/third_party/java/jopt-simple/src/main/java/joptsimple/ArgumentAcceptingOptionSpec.java new file mode 100644 index 0000000000..ca4c59f0b0 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/ArgumentAcceptingOptionSpec.java @@ -0,0 +1,329 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +import static java.util.Collections.*; +import static java.util.Objects.*; + +import static joptsimple.internal.Reflection.*; +import static joptsimple.internal.Strings.*; + +/** + * <p>Specification of an option that accepts an argument.</p> + * + * <p>Instances are returned from {@link OptionSpecBuilder} methods to allow the formation of parser directives as + * sentences in a "fluent interface" language. For example:</p> + * + * <pre> + * <code> + * OptionParser parser = new OptionParser(); + * parser.accepts( "c" ).withRequiredArg().<strong>ofType( Integer.class )</strong>; + * </code> + * </pre> + * + * <p>If no methods are invoked on an instance of this class, then that instance's option will treat its argument as + * a {@link String}.</p> + * + * @param <V> represents the type of the arguments this option accepts + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public abstract class ArgumentAcceptingOptionSpec<V> extends AbstractOptionSpec<V> { + private static final char NIL_VALUE_SEPARATOR = '\u0000'; + + private final boolean argumentRequired; + private final List<V> defaultValues = new ArrayList<>(); + + private boolean optionRequired; + private ValueConverter<V> converter; + private String argumentDescription = ""; + private String valueSeparator = String.valueOf( NIL_VALUE_SEPARATOR ); + + ArgumentAcceptingOptionSpec( String option, boolean argumentRequired ) { + super( option ); + + this.argumentRequired = argumentRequired; + } + + ArgumentAcceptingOptionSpec( List<String> options, boolean argumentRequired, String description ) { + super( options, description ); + + this.argumentRequired = argumentRequired; + } + + /** + * <p>Specifies a type to which arguments of this spec's option are to be converted.</p> + * + * <p>JOpt Simple accepts types that have either:</p> + * + * <ol> + * <li>a public static method called {@code valueOf} which accepts a single argument of type {@link String} + * and whose return type is the same as the class on which the method is declared. The {@code java.lang} + * primitive wrapper classes have such methods.</li> + * + * <li>a public constructor which accepts a single argument of type {@link String}.</li> + * </ol> + * + * <p>This class converts arguments using those methods in that order; that is, {@code valueOf} would be invoked + * before a one-{@link String}-arg constructor would.</p> + * + * <p>Invoking this method will trump any previous calls to this method or to + * {@link #withValuesConvertedBy(ValueConverter)}.</p> + * + * @param <T> represents the runtime class of the desired option argument type + * @param argumentType desired type of arguments to this spec's option + * @return self, so that the caller can add clauses to the fluent interface sentence + * @throws NullPointerException if the type is {@code null} + * @throws IllegalArgumentException if the type does not have the standard conversion methods + */ + public final <T> ArgumentAcceptingOptionSpec<T> ofType( Class<T> argumentType ) { + return withValuesConvertedBy( findConverter( argumentType ) ); + } + + /** + * <p>Specifies a converter to use to translate arguments of this spec's option into Java objects. This is useful + * when converting to types that do not have the requisite factory method or constructor for + * {@link #ofType(Class)}.</p> + * + * <p>Invoking this method will trump any previous calls to this method or to {@link #ofType(Class)}. + * + * @param <T> represents the runtime class of the desired option argument type + * @param aConverter the converter to use + * @return self, so that the caller can add clauses to the fluent interface sentence + * @throws NullPointerException if the converter is {@code null} + */ + @SuppressWarnings( "unchecked" ) + public final <T> ArgumentAcceptingOptionSpec<T> withValuesConvertedBy( ValueConverter<T> aConverter ) { + if ( aConverter == null ) + throw new NullPointerException( "illegal null converter" ); + + converter = (ValueConverter<V>) aConverter; + return (ArgumentAcceptingOptionSpec<T>) this; + } + + /** + * <p>Specifies a description for the argument of the option that this spec represents. This description is used + * when generating help information about the parser.</p> + * + * @param description describes the nature of the argument of this spec's option + * @return self, so that the caller can add clauses to the fluent interface sentence + */ + public final ArgumentAcceptingOptionSpec<V> describedAs( String description ) { + argumentDescription = description; + return this; + } + + /** + * <p>Specifies a value separator for the argument of the option that this spec represents. This allows a single + * option argument to represent multiple values for the option. For example:</p> + * + * <pre> + * <code> + * parser.accepts( "z" ).withRequiredArg() + * .<strong>withValuesSeparatedBy( ',' )</strong>; + * OptionSet options = parser.parse( new String[] { "-z", "foo,bar,baz", "-z", + * "fizz", "-z", "buzz" } ); + * </code> + * </pre> + * + * <p>Then <code>options.valuesOf( "z" )</code> would yield the list {@code [foo, bar, baz, fizz, buzz]}.</p> + * + * <p>You cannot use Unicode U+0000 as the separator.</p> + * + * @param separator a character separator + * @return self, so that the caller can add clauses to the fluent interface sentence + * @throws IllegalArgumentException if the separator is Unicode U+0000 + */ + public final ArgumentAcceptingOptionSpec<V> withValuesSeparatedBy( char separator ) { + if ( separator == NIL_VALUE_SEPARATOR ) + throw new IllegalArgumentException( "cannot use U+0000 as separator" ); + + valueSeparator = String.valueOf( separator ); + return this; + } + + /** + * <p>Specifies a value separator for the argument of the option that this spec represents. This allows a single + * option argument to represent multiple values for the option. For example:</p> + * + * <pre> + * <code> + * parser.accepts( "z" ).withRequiredArg() + * .<strong>withValuesSeparatedBy( ":::" )</strong>; + * OptionSet options = parser.parse( new String[] { "-z", "foo:::bar:::baz", "-z", + * "fizz", "-z", "buzz" } ); + * </code> + * </pre> + * + * <p>Then <code>options.valuesOf( "z" )</code> would yield the list {@code [foo, bar, baz, fizz, buzz]}.</p> + * + * <p>You cannot use Unicode U+0000 in the separator.</p> + * + * @param separator a string separator + * @return self, so that the caller can add clauses to the fluent interface sentence + * @throws IllegalArgumentException if the separator contains Unicode U+0000 + */ + public final ArgumentAcceptingOptionSpec<V> withValuesSeparatedBy( String separator ) { + if ( separator.indexOf( NIL_VALUE_SEPARATOR ) != -1 ) + throw new IllegalArgumentException( "cannot use U+0000 in separator" ); + + valueSeparator = separator; + return this; + } + + /** + * Specifies a set of default values for the argument of the option that this spec represents. + * + * @param value the first in the set of default argument values for this spec's option + * @param values the (optional) remainder of the set of default argument values for this spec's option + * @return self, so that the caller can add clauses to the fluent interface sentence + * @throws NullPointerException if {@code value}, {@code values}, or any elements of {@code values} are + * {@code null} + */ + @SafeVarargs + public final ArgumentAcceptingOptionSpec<V> defaultsTo( V value, V... values ) { + addDefaultValue( value ); + defaultsTo( values ); + + return this; + } + + /** + * Specifies a set of default values for the argument of the option that this spec represents. + * + * @param values the set of default argument values for this spec's option + * @return self, so that the caller can add clauses to the fluent interface sentence + * @throws NullPointerException if {@code values} or any elements of {@code values} are {@code null} + */ + public ArgumentAcceptingOptionSpec<V> defaultsTo( V[] values ) { + for ( V each : values ) + addDefaultValue( each ); + + return this; + } + + /** + * Marks this option as required. An {@link OptionException} will be thrown when + * {@link OptionParser#parse(java.lang.String...)} is called, if an option is marked as required and not specified + * on the command line. + * + * @return self, so that the caller can add clauses to the fluent interface sentence + */ + public ArgumentAcceptingOptionSpec<V> required() { + optionRequired = true; + return this; + } + + public boolean isRequired() { + return optionRequired; + } + + private void addDefaultValue( V value ) { + requireNonNull( value ); + defaultValues.add( value ); + } + + @Override + final void handleOption( OptionParser parser, ArgumentList arguments, OptionSet detectedOptions, + String detectedArgument ) { + + if ( isNullOrEmpty( detectedArgument ) ) + detectOptionArgument( parser, arguments, detectedOptions ); + else + addArguments( detectedOptions, detectedArgument ); + } + + protected void addArguments( OptionSet detectedOptions, String detectedArgument ) { + StringTokenizer lexer = new StringTokenizer( detectedArgument, valueSeparator ); + if ( !lexer.hasMoreTokens() ) + detectedOptions.addWithArgument( this, detectedArgument ); + else { + while ( lexer.hasMoreTokens() ) + detectedOptions.addWithArgument( this, lexer.nextToken() ); + } + } + + protected abstract void detectOptionArgument( OptionParser parser, ArgumentList arguments, + OptionSet detectedOptions ); + + @Override + protected final V convert( String argument ) { + return convertWith( converter, argument ); + } + + protected boolean canConvertArgument( String argument ) { + StringTokenizer lexer = new StringTokenizer( argument, valueSeparator ); + + try { + while ( lexer.hasMoreTokens() ) + convert( lexer.nextToken() ); + return true; + } catch ( OptionException ignored ) { + return false; + } + } + + protected boolean isArgumentOfNumberType() { + return converter != null && Number.class.isAssignableFrom( converter.valueType() ); + } + + public boolean acceptsArguments() { + return true; + } + + public boolean requiresArgument() { + return argumentRequired; + } + + public String argumentDescription() { + return argumentDescription; + } + + public String argumentTypeIndicator() { + return argumentTypeIndicatorFrom( converter ); + } + + public List<V> defaultValues() { + return unmodifiableList( defaultValues ); + } + + @Override + public boolean equals( Object that ) { + if ( !super.equals( that ) ) + return false; + + ArgumentAcceptingOptionSpec<?> other = (ArgumentAcceptingOptionSpec<?>) that; + return requiresArgument() == other.requiresArgument(); + } + + @Override + public int hashCode() { + return super.hashCode() ^ ( argumentRequired ? 0 : 1 ); + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/ArgumentList.java b/third_party/java/jopt-simple/src/main/java/joptsimple/ArgumentList.java new file mode 100644 index 0000000000..744f31aa21 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/ArgumentList.java @@ -0,0 +1,59 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static joptsimple.ParserRules.*; + +/** + * <p>Wrapper for an array of command line arguments.</p> + * + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +class ArgumentList { + private final String[] arguments; + private int currentIndex; + + ArgumentList( String... arguments ) { + this.arguments = arguments.clone(); + } + + boolean hasMore() { + return currentIndex < arguments.length; + } + + String next() { + return arguments[ currentIndex++ ]; + } + + String peek() { + return arguments[ currentIndex ]; + } + + void treatNextAsLongOption() { + if ( HYPHEN_CHAR != arguments[ currentIndex ].charAt( 0 ) ) + arguments[ currentIndex ] = DOUBLE_HYPHEN + arguments[ currentIndex ]; + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/BuiltinHelpFormatter.java b/third_party/java/jopt-simple/src/main/java/joptsimple/BuiltinHelpFormatter.java new file mode 100644 index 0000000000..51ec603e6f --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/BuiltinHelpFormatter.java @@ -0,0 +1,565 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.*; + +import joptsimple.internal.Messages; +import joptsimple.internal.Rows; +import joptsimple.internal.Strings; + +import static joptsimple.ParserRules.*; +import static joptsimple.internal.Classes.*; +import static joptsimple.internal.Strings.*; + +/** + * <p>A help formatter that allows configuration of overall row width and column separator width.</p> + * + * <p>The formatter produces output in two sections: one for the options, and one for non-option arguments.</p> + * + * <p>The options section has two columns: the left column for the options, and the right column for their + * descriptions. The formatter will allow as much space as possible for the descriptions, by minimizing the option + * column's width, no greater than slightly less than half the overall desired width.</p> + * + * <p>The non-option arguments section is one column, occupying as much width as it can.</p> + * + * <p>Subclasses are free to override bits of this implementation as they see fit. Inspect the code + * carefully to understand the flow of control that this implementation guarantees.</p> + * + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class BuiltinHelpFormatter implements HelpFormatter { + private final Rows nonOptionRows; + private final Rows optionRows; + + /** + * Makes a formatter with a pre-configured overall row width and column separator width. + */ + BuiltinHelpFormatter() { + this( 80, 2 ); + } + + /** + * Makes a formatter with a given overall row width and column separator width. + * + * @param desiredOverallWidth how many characters wide to make the overall help display + * @param desiredColumnSeparatorWidth how many characters wide to make the separation between option column and + * description column + */ + public BuiltinHelpFormatter( int desiredOverallWidth, int desiredColumnSeparatorWidth ) { + nonOptionRows = new Rows( desiredOverallWidth * 2, 0 ); + optionRows = new Rows( desiredOverallWidth, desiredColumnSeparatorWidth ); + } + + /** + * {@inheritDoc} + * + * <p>This implementation:</p> + * <ul> + * <li>Sorts the given descriptors by their first elements of {@link OptionDescriptor#options()}</li> + * <li>Passes the resulting sorted set to {@link #addRows(java.util.Collection)}</li> + * <li>Returns the result of {@link #formattedHelpOutput()}</li> + * </ul> + */ + public String format( Map<String, ? extends OptionDescriptor> options ) { + optionRows.reset(); + nonOptionRows.reset(); + + Comparator<OptionDescriptor> comparator = + new Comparator<OptionDescriptor>() { + public int compare( OptionDescriptor first, OptionDescriptor second ) { + return first.options().iterator().next().compareTo( second.options().iterator().next() ); + } + }; + + Set<OptionDescriptor> sorted = new TreeSet<>( comparator ); + sorted.addAll( options.values() ); + + addRows( sorted ); + + return formattedHelpOutput(); + } + + /** + * Adds a row of option help output in the left column, with empty space in the right column. + * + * @param single text to put in the left column + */ + protected void addOptionRow( String single ) { + addOptionRow( single, "" ); + } + + /** + * Adds a row of option help output in the left and right columns. + * + * @param left text to put in the left column + * @param right text to put in the right column + */ + protected void addOptionRow( String left, String right ) { + optionRows.add( left, right ); + } + + /** + * Adds a single row of non-option argument help. + * + * @param single single row of non-option argument help text + */ + protected void addNonOptionRow( String single ) { + nonOptionRows.add( single, "" ); + } + + /** + * Resizes the columns of all the rows to be no wider than the widest element in that column. + */ + protected void fitRowsToWidth() { + nonOptionRows.fitToWidth(); + optionRows.fitToWidth(); + } + + /** + * Produces non-option argument help. + * + * @return non-option argument help + */ + protected String nonOptionOutput() { + return nonOptionRows.render(); + } + + /** + * Produces help for options and their descriptions. + * + * @return option help + */ + protected String optionOutput() { + return optionRows.render(); + } + + /** + * <p>Produces help output for an entire set of options and non-option arguments.</p> + * + * <p>This implementation concatenates:</p> + * <ul> + * <li>the result of {@link #nonOptionOutput()}</li> + * <li>if there is non-option output, a line separator</li> + * <li>the result of {@link #optionOutput()}</li> + * </ul> + * + * @return help output for entire set of options and non-option arguments + */ + protected String formattedHelpOutput() { + StringBuilder formatted = new StringBuilder(); + String nonOptionDisplay = nonOptionOutput(); + if ( !Strings.isNullOrEmpty( nonOptionDisplay ) ) + formatted.append( nonOptionDisplay ).append( LINE_SEPARATOR ); + formatted.append( optionOutput() ); + + return formatted.toString(); + } + + /** + * <p>Adds rows of help output for the given options.</p> + * + * <p>This implementation:</p> + * <ul> + * <li>Calls {@link #addNonOptionsDescription(java.util.Collection)} with the options as the argument</li> + * <li>If there are no options, calls {@link #addOptionRow(String)} with an argument that indicates + * that no options are specified.</li> + * <li>Otherwise, calls {@link #addHeaders(java.util.Collection)} with the options as the argument, + * followed by {@link #addOptions(java.util.Collection)} with the options as the argument.</li> + * <li>Calls {@link #fitRowsToWidth()}.</li> + * </ul> + * + * @param options descriptors for the configured options of a parser + */ + protected void addRows( Collection<? extends OptionDescriptor> options ) { + addNonOptionsDescription( options ); + + if ( options.isEmpty() ) + addOptionRow( message( "no.options.specified" ) ); + else { + addHeaders( options ); + addOptions( options ); + } + + fitRowsToWidth(); + } + + /** + * <p>Adds non-option arguments descriptions to the help output.</p> + * + * <p>This implementation:</p> + * <ul> + * <li>{@linkplain #findAndRemoveNonOptionsSpec(java.util.Collection) Finds and removes the non-option + * arguments descriptor}</li> + * <li>{@linkplain #shouldShowNonOptionArgumentDisplay(OptionDescriptor) Decides whether there is + * anything to show for non-option arguments}</li> + * <li>If there is, {@linkplain #addNonOptionRow(String) adds a header row} and + * {@linkplain #addNonOptionRow(String) adds a} + * {@linkplain #createNonOptionArgumentsDisplay(OptionDescriptor) non-option arguments description} </li> + * </ul> + * + * @param options descriptors for the configured options of a parser + */ + protected void addNonOptionsDescription( Collection<? extends OptionDescriptor> options ) { + OptionDescriptor nonOptions = findAndRemoveNonOptionsSpec( options ); + if ( shouldShowNonOptionArgumentDisplay( nonOptions ) ) { + addNonOptionRow( message( "non.option.arguments.header" ) ); + addNonOptionRow( createNonOptionArgumentsDisplay( nonOptions ) ); + } + } + + /** + * <p>Decides whether or not to show a non-option arguments help.</p> + * + * <p>This implementation responds with {@code true} if the non-option descriptor has a non-{@code null}, + * non-empty value for any of {@link OptionDescriptor#description()}, + * {@link OptionDescriptor#argumentTypeIndicator()}, or {@link OptionDescriptor#argumentDescription()}.</p> + * + * @param nonOptionDescriptor non-option argument descriptor + * @return {@code true} if non-options argument help should be shown + */ + protected boolean shouldShowNonOptionArgumentDisplay( OptionDescriptor nonOptionDescriptor ) { + return !Strings.isNullOrEmpty( nonOptionDescriptor.description() ) + || !Strings.isNullOrEmpty( nonOptionDescriptor.argumentTypeIndicator() ) + || !Strings.isNullOrEmpty( nonOptionDescriptor.argumentDescription() ); + } + + /** + * <p>Creates a non-options argument help string.</p> + * + * <p>This implementation creates an empty string buffer and calls + * {@link #maybeAppendOptionInfo(StringBuilder, OptionDescriptor)} + * and {@link #maybeAppendNonOptionsDescription(StringBuilder, OptionDescriptor)}, passing them the + * buffer and the non-option arguments descriptor.</p> + * + * @param nonOptionDescriptor non-option argument descriptor + * @return help string for non-options + */ + protected String createNonOptionArgumentsDisplay( OptionDescriptor nonOptionDescriptor ) { + StringBuilder buffer = new StringBuilder(); + maybeAppendOptionInfo( buffer, nonOptionDescriptor ); + maybeAppendNonOptionsDescription( buffer, nonOptionDescriptor ); + + return buffer.toString(); + } + + /** + * <p>Appends help for the given non-option arguments descriptor to the given buffer.</p> + * + * <p>This implementation appends {@code " -- "} if the buffer has text in it and the non-option arguments + * descriptor has a {@link OptionDescriptor#description()}; followed by the + * {@link OptionDescriptor#description()}.</p> + * + * @param buffer string buffer + * @param nonOptions non-option arguments descriptor + */ + protected void maybeAppendNonOptionsDescription( StringBuilder buffer, OptionDescriptor nonOptions ) { + buffer.append( buffer.length() > 0 && !Strings.isNullOrEmpty( nonOptions.description() ) ? " -- " : "" ) + .append( nonOptions.description() ); + } + + /** + * Finds the non-option arguments descriptor in the given collection, removes it, and returns it. + * + * @param options descriptors for the configured options of a parser + * @return the non-option arguments descriptor + */ + protected OptionDescriptor findAndRemoveNonOptionsSpec( Collection<? extends OptionDescriptor> options ) { + for ( Iterator<? extends OptionDescriptor> it = options.iterator(); it.hasNext(); ) { + OptionDescriptor next = it.next(); + if ( next.representsNonOptions() ) { + it.remove(); + return next; + } + } + + throw new AssertionError( "no non-options argument spec" ); + } + + /** + * <p>Adds help row headers for option help columns.</p> + * + * <p>This implementation uses the headers {@code "Option"} and {@code "Description"}. If the options contain + * a "required" option, the {@code "Option"} header looks like {@code "Option (* = required)}. Both headers + * are "underlined" using {@code "-"}.</p> + * + * @param options descriptors for the configured options of a parser + */ + protected void addHeaders( Collection<? extends OptionDescriptor> options ) { + if ( hasRequiredOption( options ) ) { + addOptionRow( message( "option.header.with.required.indicator" ), message( "description.header" ) ); + addOptionRow( message( "option.divider.with.required.indicator" ), message( "description.divider" ) ); + } else { + addOptionRow( message( "option.header" ), message( "description.header" ) ); + addOptionRow( message( "option.divider" ), message( "description.divider" ) ); + } + } + + /** + * Tells whether the given option descriptors contain a "required" option. + * + * @param options descriptors for the configured options of a parser + * @return {@code true} if at least one of the options is "required" + */ + protected final boolean hasRequiredOption( Collection<? extends OptionDescriptor> options ) { + for ( OptionDescriptor each : options ) { + if ( each.isRequired() ) + return true; + } + + return false; + } + + /** + * <p>Adds help rows for the given options.</p> + * + * <p>This implementation loops over the given options, and for each, calls {@link #addOptionRow(String, String)} + * using the results of {@link #createOptionDisplay(OptionDescriptor)} and + * {@link #createDescriptionDisplay(OptionDescriptor)}, respectively, as arguments.</p> + * + * @param options descriptors for the configured options of a parser + */ + protected void addOptions( Collection<? extends OptionDescriptor> options ) { + for ( OptionDescriptor each : options ) { + if ( !each.representsNonOptions() ) + addOptionRow( createOptionDisplay( each ), createDescriptionDisplay( each ) ); + } + } + + /** + * <p>Creates a string for how the given option descriptor is to be represented in help.</p> + * + * <p>This implementation gives a string consisting of the concatenation of:</p> + * <ul> + * <li>{@code "* "} for "required" options, otherwise {@code ""}</li> + * <li>For each of the {@link OptionDescriptor#options()} of the descriptor, separated by {@code ", "}: + * <ul> + * <li>{@link #optionLeader(String)} of the option</li> + * <li>the option</li> + * </ul> + * </li> + * <li>the result of {@link #maybeAppendOptionInfo(StringBuilder, OptionDescriptor)}</li> + * </ul> + * + * @param descriptor a descriptor for a configured option of a parser + * @return help string + */ + protected String createOptionDisplay( OptionDescriptor descriptor ) { + StringBuilder buffer = new StringBuilder( descriptor.isRequired() ? "* " : "" ); + + for ( Iterator<String> i = descriptor.options().iterator(); i.hasNext(); ) { + String option = i.next(); + buffer.append( optionLeader( option ) ); + buffer.append( option ); + + if ( i.hasNext() ) + buffer.append( ", " ); + } + + maybeAppendOptionInfo( buffer, descriptor ); + + return buffer.toString(); + } + + /** + * <p>Gives a string that represents the given option's "option leader" in help.</p> + * + * <p>This implementation answers with {@code "--"} for options of length greater than one; otherwise answers + * with {@code "-"}.</p> + * + * @param option a string option + * @return an "option leader" string + */ + protected String optionLeader( String option ) { + return option.length() > 1 ? DOUBLE_HYPHEN : HYPHEN; + } + + /** + * <p>Appends additional info about the given option to the given buffer.</p> + * + * <p>This implementation:</p> + * <ul> + * <li>calls {@link #extractTypeIndicator(OptionDescriptor)} for the descriptor</li> + * <li>calls {@link joptsimple.OptionDescriptor#argumentDescription()} for the descriptor</li> + * <li>if either of the above is present, calls + * {@link #appendOptionHelp(StringBuilder, String, String, boolean)}</li> + * </ul> + * + * @param buffer string buffer + * @param descriptor a descriptor for a configured option of a parser + */ + protected void maybeAppendOptionInfo( StringBuilder buffer, OptionDescriptor descriptor ) { + String indicator = extractTypeIndicator( descriptor ); + String description = descriptor.argumentDescription(); + if ( descriptor.acceptsArguments() + || !isNullOrEmpty( description ) + || descriptor.representsNonOptions() ) { + + appendOptionHelp( buffer, indicator, description, descriptor.requiresArgument() ); + } + } + + /** + * <p>Gives an indicator of the type of arguments of the option described by the given descriptor, + * for use in help.</p> + * + * <p>This implementation asks for the {@link OptionDescriptor#argumentTypeIndicator()} of the given + * descriptor, and if it is present and not {@code "java.lang.String"}, parses it as a fully qualified + * class name and returns the base name of that class; otherwise returns {@code "String"}.</p> + * + * @param descriptor a descriptor for a configured option of a parser + * @return type indicator text + */ + protected String extractTypeIndicator( OptionDescriptor descriptor ) { + String indicator = descriptor.argumentTypeIndicator(); + + if ( !isNullOrEmpty( indicator ) && !String.class.getName().equals( indicator ) ) + return shortNameOf( indicator ); + + return "String"; + } + + /** + * <p>Appends info about an option's argument to the given buffer.</p> + * + * <p>This implementation calls {@link #appendTypeIndicator(StringBuilder, String, String, char, char)} with + * the surrounding characters {@code '<'} and {@code '>'} for options with {@code required} arguments, and + * with the surrounding characters {@code '['} and {@code ']'} for options with optional arguments.</p> + * + * @param buffer string buffer + * @param typeIndicator type indicator + * @param description type description + * @param required indicator of "required"-ness of the argument of the option + */ + protected void appendOptionHelp( StringBuilder buffer, String typeIndicator, String description, + boolean required ) { + if ( required ) + appendTypeIndicator( buffer, typeIndicator, description, '<', '>' ); + else + appendTypeIndicator( buffer, typeIndicator, description, '[', ']' ); + } + + /** + * <p>Appends a type indicator for an option's argument to the given buffer.</p> + * + * <p>This implementation appends, in order:</p> + * <ul> + * <li>{@code ' '}</li> + * <li>{@code start}</li> + * <li>the type indicator, if not {@code null}</li> + * <li>if the description is present, then {@code ": "} plus the description if the type indicator is + * present; otherwise the description only</li> + * <li>{@code end}</li> + * </ul> + * + * @param buffer string buffer + * @param typeIndicator type indicator + * @param description type description + * @param start starting character + * @param end ending character + */ + protected void appendTypeIndicator( StringBuilder buffer, String typeIndicator, String description, + char start, char end ) { + buffer.append( ' ' ).append( start ); + if ( typeIndicator != null ) + buffer.append( typeIndicator ); + + if ( !Strings.isNullOrEmpty( description ) ) { + if ( typeIndicator != null ) + buffer.append( ": " ); + + buffer.append( description ); + } + + buffer.append( end ); + } + + /** + * <p>Gives a string representing a description of the option with the given descriptor.</p> + * + * <p>This implementation:</p> + * <ul> + * <li>Asks for the descriptor's {@link OptionDescriptor#defaultValues()}</li> + * <li>If they're not present, answers the descriptor's {@link OptionDescriptor#description()}.</li> + * <li>If they are present, concatenates and returns: + * <ul> + * <li>the descriptor's {@link OptionDescriptor#description()}</li> + * <li>{@code ' '}</li> + * <li>{@code "default: "} plus the result of {@link #createDefaultValuesDisplay(java.util.List)}, + * surrounded by parentheses</li> + * </ul> + * </li> + * </ul> + * + * @param descriptor a descriptor for a configured option of a parser + * @return display text for the option's description + */ + protected String createDescriptionDisplay( OptionDescriptor descriptor ) { + List<?> defaultValues = descriptor.defaultValues(); + if ( defaultValues.isEmpty() ) + return descriptor.description(); + + String defaultValuesDisplay = createDefaultValuesDisplay( defaultValues ); + return ( descriptor.description() + + ' ' + + surround( message( "default.value.header" ) + ' ' + defaultValuesDisplay, '(', ')' ) + ).trim(); + } + + /** + * <p>Gives a display string for the default values of an option's argument.</p> + * + * <p>This implementation gives the {@link Object#toString()} of the first value if there is only one value, + * otherwise gives the {@link Object#toString()} of the whole list.</p> + * + * @param defaultValues some default values for a given option's argument + * @return a display string for those default values + */ + protected String createDefaultValuesDisplay( List<?> defaultValues ) { + return defaultValues.size() == 1 ? defaultValues.get( 0 ).toString() : defaultValues.toString(); + } + + /** + * <p>Looks up and gives a resource bundle message.</p> + * + * <p>This implementation looks in the bundle {@code "joptsimple.HelpFormatterMessages"} in the default + * locale, using a key that is the concatenation of this class's fully qualified name, {@code '.'}, + * and the given key suffix, formats the corresponding value using the given arguments, and returns + * the result.</p> + * + * @param keySuffix suffix to use when looking up the bundle message + * @param args arguments to fill in the message template with + * @return a formatted localized message + */ + protected String message( String keySuffix, Object... args ) { + return Messages.message( + Locale.getDefault(), + "joptsimple.HelpFormatterMessages", + BuiltinHelpFormatter.class, + keySuffix, + args ); + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/HelpFormatter.java b/third_party/java/jopt-simple/src/main/java/joptsimple/HelpFormatter.java new file mode 100644 index 0000000000..d178d70c09 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/HelpFormatter.java @@ -0,0 +1,45 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.Map; + +/** + * <p>Represents objects charged with taking a set of option descriptions and producing some help text from them.</p> + * + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public interface HelpFormatter { + /** + * Produces help text, given a set of option descriptors. + * + * @param options descriptors for the configured options of a parser + * @return text to be used as help + * @see OptionParser#printHelpOn(java.io.Writer) + * @see OptionParser#formatHelpWith(HelpFormatter) + */ + String format( Map<String, ? extends OptionDescriptor> options ); +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/IllegalOptionSpecificationException.java b/third_party/java/jopt-simple/src/main/java/joptsimple/IllegalOptionSpecificationException.java new file mode 100644 index 0000000000..214791544c --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/IllegalOptionSpecificationException.java @@ -0,0 +1,46 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Collections.*; + +/** + * Thrown when the option parser is asked to recognize an option with illegal characters in it. + * + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +class IllegalOptionSpecificationException extends OptionException { + private static final long serialVersionUID = -1L; + + IllegalOptionSpecificationException( String option ) { + super( singletonList( option ) ); + } + + @Override + Object[] messageArguments() { + return new Object[] { singleOptionString() }; + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/MissingRequiredOptionsException.java b/third_party/java/jopt-simple/src/main/java/joptsimple/MissingRequiredOptionsException.java new file mode 100644 index 0000000000..dcb829f342 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/MissingRequiredOptionsException.java @@ -0,0 +1,46 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.List; + +/** + * Thrown when options marked as required are not specified on the command line. + * + * @author <a href="https://github.com/TC1">Emils Solmanis</a> + */ +class MissingRequiredOptionsException extends OptionException { + private static final long serialVersionUID = -1L; + + protected MissingRequiredOptionsException( List<? extends OptionSpec<?>> missingRequiredOptions ) { + super( missingRequiredOptions ); + } + + @Override + Object[] messageArguments() { + return new Object[] { multipleOptionString() }; + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/MultipleArgumentsForOptionException.java b/third_party/java/jopt-simple/src/main/java/joptsimple/MultipleArgumentsForOptionException.java new file mode 100644 index 0000000000..12d1485a39 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/MultipleArgumentsForOptionException.java @@ -0,0 +1,46 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Collections.*; + +/** + * Thrown when asking an {@link OptionSet} for a single argument of an option when many have been specified. + * + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +class MultipleArgumentsForOptionException extends OptionException { + private static final long serialVersionUID = -1L; + + MultipleArgumentsForOptionException( OptionSpec<?> options ) { + super( singleton( options ) ); + } + + @Override + Object[] messageArguments() { + return new Object[] { singleOptionString() }; + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/NoArgumentOptionSpec.java b/third_party/java/jopt-simple/src/main/java/joptsimple/NoArgumentOptionSpec.java new file mode 100644 index 0000000000..82ac521772 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/NoArgumentOptionSpec.java @@ -0,0 +1,81 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.List; + +import static java.util.Collections.*; + +/** + * A specification for an option that does not accept arguments. + * + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +class NoArgumentOptionSpec extends AbstractOptionSpec<Void> { + NoArgumentOptionSpec( String option ) { + this( singletonList( option ), "" ); + } + + NoArgumentOptionSpec( List<String> options, String description ) { + super( options, description ); + } + + @Override + void handleOption( OptionParser parser, ArgumentList arguments, OptionSet detectedOptions, + String detectedArgument ) { + + detectedOptions.add( this ); + } + + public boolean acceptsArguments() { + return false; + } + + public boolean requiresArgument() { + return false; + } + + public boolean isRequired() { + return false; + } + + public String argumentDescription() { + return ""; + } + + public String argumentTypeIndicator() { + return ""; + } + + @Override + protected Void convert( String argument ) { + return null; + } + + public List<Void> defaultValues() { + return emptyList(); + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/NonOptionArgumentSpec.java b/third_party/java/jopt-simple/src/main/java/joptsimple/NonOptionArgumentSpec.java new file mode 100644 index 0000000000..7343d42c2a --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/NonOptionArgumentSpec.java @@ -0,0 +1,170 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.List; + +import static java.util.Arrays.*; +import static java.util.Collections.*; +import static joptsimple.internal.Reflection.*; + +/** + * <p>Specification of a command line's non-option arguments.</p> + * + * <p>Instances are returned from {@link OptionParser} methods to allow the formation of parser directives as + * sentences in a "fluent interface" language. For example:</p> + * + * <pre> + * <code> + * OptionParser parser = new OptionParser(); + * parser.nonOptions( "files to be processed" ).<strong>ofType( File.class )</strong>; + * </code> + * </pre> + * + * <p>If no methods are invoked on an instance of this class, then that instance's option will treat the non-option + * arguments as {@link String}s.</p> + * + * @param <V> represents the type of the non-option arguments + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class NonOptionArgumentSpec<V> extends AbstractOptionSpec<V> { + static final String NAME = "[arguments]"; + + private ValueConverter<V> converter; + private String argumentDescription = ""; + + NonOptionArgumentSpec() { + this( "" ); + } + + NonOptionArgumentSpec( String description ) { + super( asList( NAME ), description ); + } + + /** + * <p>Specifies a type to which the non-option arguments are to be converted.</p> + * + * <p>JOpt Simple accepts types that have either:</p> + * + * <ol> + * <li>a public static method called {@code valueOf} which accepts a single argument of type {@link String} + * and whose return type is the same as the class on which the method is declared. The {@code java.lang} + * primitive wrapper classes have such methods.</li> + * + * <li>a public constructor which accepts a single argument of type {@link String}.</li> + * </ol> + * + * <p>This class converts arguments using those methods in that order; that is, {@code valueOf} would be invoked + * before a one-{@link String}-arg constructor would.</p> + * + * <p>Invoking this method will trump any previous calls to this method or to + * {@link #withValuesConvertedBy(ValueConverter)}.</p> + * + * @param <T> represents the runtime class of the desired option argument type + * @param argumentType desired type of arguments to this spec's option + * @return self, so that the caller can add clauses to the fluent interface sentence + * @throws NullPointerException if the type is {@code null} + * @throws IllegalArgumentException if the type does not have the standard conversion methods + */ + @SuppressWarnings( "unchecked" ) + public <T> NonOptionArgumentSpec<T> ofType( Class<T> argumentType ) { + converter = (ValueConverter<V>) findConverter( argumentType ); + return (NonOptionArgumentSpec<T>) this; + } + + /** + * <p>Specifies a converter to use to translate non-option arguments into Java objects. This is useful + * when converting to types that do not have the requisite factory method or constructor for + * {@link #ofType(Class)}.</p> + * + * <p>Invoking this method will trump any previous calls to this method or to {@link #ofType(Class)}. + * + * @param <T> represents the runtime class of the desired non-option argument type + * @param aConverter the converter to use + * @return self, so that the caller can add clauses to the fluent interface sentence + * @throws NullPointerException if the converter is {@code null} + */ + @SuppressWarnings( "unchecked" ) + public final <T> NonOptionArgumentSpec<T> withValuesConvertedBy( ValueConverter<T> aConverter ) { + if ( aConverter == null ) + throw new NullPointerException( "illegal null converter" ); + + converter = (ValueConverter<V>) aConverter; + return (NonOptionArgumentSpec<T>) this; + } + + /** + * <p>Specifies a description for the non-option arguments that this spec represents. This description is used + * when generating help information about the parser.</p> + * + * @param description describes the nature of the argument of this spec's option + * @return self, so that the caller can add clauses to the fluent interface sentence + */ + public NonOptionArgumentSpec<V> describedAs( String description ) { + argumentDescription = description; + return this; + } + + @Override + protected final V convert( String argument ) { + return convertWith( converter, argument ); + } + + @Override + void handleOption( OptionParser parser, ArgumentList arguments, OptionSet detectedOptions, + String detectedArgument ) { + + detectedOptions.addWithArgument( this, detectedArgument ); + } + + public List<?> defaultValues() { + return emptyList(); + } + + public boolean isRequired() { + return false; + } + + public boolean acceptsArguments() { + return false; + } + + public boolean requiresArgument() { + return false; + } + + public String argumentDescription() { + return argumentDescription; + } + + public String argumentTypeIndicator() { + return argumentTypeIndicatorFrom( converter ); + } + + public boolean representsNonOptions() { + return true; + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/OptionArgumentConversionException.java b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionArgumentConversionException.java new file mode 100644 index 0000000000..193557d8fa --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionArgumentConversionException.java @@ -0,0 +1,50 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Collections.*; + +/** + * Thrown when a problem occurs converting an argument of an option from {@link String} to another type. + * + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +class OptionArgumentConversionException extends OptionException { + private static final long serialVersionUID = -1L; + + private final String argument; + + OptionArgumentConversionException( OptionSpec<?> options, String argument, Throwable cause ) { + super( singleton( options ), cause ); + + this.argument = argument; + } + + @Override + Object[] messageArguments() { + return new Object[] { argument, singleOptionString() }; + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/OptionDeclarer.java b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionDeclarer.java new file mode 100644 index 0000000000..7d54653443 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionDeclarer.java @@ -0,0 +1,116 @@ +package joptsimple; + +import java.util.List; + +/** + * Trains the option parser. This interface aids integration that disposes declaration of options but not actual + * command-line parsing. + * + * Typical use is for another class to implement {@code OptionDeclarer} as a facade, forwarding calls to an + * {@code OptionParser} instance. + * + * Note that although this is an interface, the returned values of calls are concrete jopt-simple classes. + * + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + * @see OptionParser + * @since 4.6 + */ +public interface OptionDeclarer { + /** + * Tells the parser to recognize the given option. + * + * <p>This method returns an instance of {@link OptionSpecBuilder} to allow the formation of parser directives + * as sentences in a fluent interface language. For example:</p> + * + * <pre><code> + * OptionDeclarer parser = new OptionParser(); + * parser.<strong>accepts( "c" )</strong>.withRequiredArg().ofType( Integer.class ); + * </code></pre> + * + * <p>If no methods are invoked on the returned {@link OptionSpecBuilder}, then the parser treats the option as + * accepting no argument.</p> + * + * @param option the option to recognize + * @return an object that can be used to flesh out more detail about the option + * @throws OptionException if the option contains illegal characters + * @throws NullPointerException if the option is {@code null} + */ + OptionSpecBuilder accepts( String option ); + + /** + * Tells the parser to recognize the given option. + * + * @see #accepts(String) + * @param option the option to recognize + * @param description a string that describes the purpose of the option. This is used when generating help + * information about the parser. + * @return an object that can be used to flesh out more detail about the option + * @throws OptionException if the option contains illegal characters + * @throws NullPointerException if the option is {@code null} + */ + OptionSpecBuilder accepts( String option, String description ); + + /** + * Tells the parser to recognize the given options, and treat them as synonymous. + * + * @see #accepts(String) + * @param options the options to recognize and treat as synonymous + * @return an object that can be used to flesh out more detail about the options + * @throws OptionException if any of the options contain illegal characters + * @throws NullPointerException if the option list or any of its elements are {@code null} + */ + OptionSpecBuilder acceptsAll( List<String> options ); + + /** + * Tells the parser to recognize the given options, and treat them as synonymous. + * + * @see #acceptsAll(List) + * @param options the options to recognize and treat as synonymous + * @param description a string that describes the purpose of the option. This is used when generating help + * information about the parser. + * @return an object that can be used to flesh out more detail about the options + * @throws OptionException if any of the options contain illegal characters + * @throws NullPointerException if the option list or any of its elements are {@code null} + * @throws IllegalArgumentException if the option list is empty + */ + OptionSpecBuilder acceptsAll( List<String> options, String description ); + + /** + * Gives an object that represents an access point for non-option arguments on a command line. + * + * @return an object that can be used to flesh out more detail about the non-option arguments + */ + NonOptionArgumentSpec<String> nonOptions(); + + /** + * Gives an object that represents an access point for non-option arguments on a command line. + * + * @see #nonOptions() + * @param description a string that describes the purpose of the non-option arguments. This is used when generating + * help information about the parser. + * @return an object that can be used to flesh out more detail about the non-option arguments + */ + NonOptionArgumentSpec<String> nonOptions( String description ); + + /** + * Tells the parser whether or not to behave "POSIX-ly correct"-ly. + * + * @param setting {@code true} if the parser should behave "POSIX-ly correct"-ly + */ + void posixlyCorrect( boolean setting ); + + /** + * <p>Tells the parser to treat unrecognized options as non-option arguments.</p> + * + * <p>If not called, then the parser raises an {@link OptionException} when it encounters an unrecognized + * option.</p> + */ + void allowsUnrecognizedOptions(); + + /** + * Tells the parser either to recognize or ignore {@code -W}-style long options. + * + * @param recognize {@code true} if the parser is to recognize the special style of long options + */ + void recognizeAlternativeLongOptions( boolean recognize ); +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/OptionDescriptor.java b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionDescriptor.java new file mode 100644 index 0000000000..f77c775223 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionDescriptor.java @@ -0,0 +1,100 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.List; + +/** + * Describes options that an option parser recognizes, in ways that might be useful to {@linkplain HelpFormatter + * help screens}. + * + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public interface OptionDescriptor { + /** + * A set of options that are mutually synonymous. + * + * @return synonymous options + */ + List<String> options(); + + /** + * Description of this option's purpose. + * + * @return a description for the option + */ + String description(); + + /** + * What values will the option take if none are specified on the command line? + * + * @return any default values for the option + */ + List<?> defaultValues(); + + /** + * Is this option {@linkplain ArgumentAcceptingOptionSpec#required() required} on a command line? + * + * @return whether the option is required + */ + boolean isRequired(); + + /** + * Does this option {@linkplain ArgumentAcceptingOptionSpec accept arguments}? + * + * @return whether the option accepts arguments + */ + boolean acceptsArguments(); + + /** + * Does this option {@linkplain OptionSpecBuilder#withRequiredArg() require an argument}? + * + * @return whether the option requires an argument + */ + boolean requiresArgument(); + + /** + * Gives a short {@linkplain ArgumentAcceptingOptionSpec#describedAs(String) description} of the option's argument. + * + * @return a description for the option's argument + */ + String argumentDescription(); + + /** + * Gives an indication of the {@linkplain ArgumentAcceptingOptionSpec#ofType(Class) expected type} of the option's + * argument. + * + * @return a description for the option's argument type + */ + String argumentTypeIndicator(); + + /** + * Tells whether this object represents the non-option arguments of a command line. + * + * @return {@code true} if this represents non-option arguments + */ + boolean representsNonOptions(); +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/OptionException.java b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionException.java new file mode 100644 index 0000000000..88e7e43f2e --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionException.java @@ -0,0 +1,125 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Locale; +import java.util.Set; + +import joptsimple.internal.Strings; + +import static java.util.Collections.*; +import static joptsimple.internal.Messages.*; + +/** + * Thrown when a problem occurs during option parsing. + * + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public abstract class OptionException extends RuntimeException { + private static final long serialVersionUID = -1L; + + private final List<String> options = new ArrayList<>(); + + protected OptionException( List<String> options ) { + this.options.addAll( options ); + } + + protected OptionException( Collection<? extends OptionSpec<?>> options ) { + this.options.addAll( specsToStrings( options ) ); + } + + protected OptionException( Collection<? extends OptionSpec<?>> options, Throwable cause ) { + super( cause ); + this.options.addAll( specsToStrings( options ) ); + } + + private List<String> specsToStrings( Collection<? extends OptionSpec<?>> options ) { + List<String> strings = new ArrayList<>(); + for ( OptionSpec<?> each : options ) + strings.add( specToString( each ) ); + return strings; + } + + private String specToString( OptionSpec<?> option ) { + return Strings.join( new ArrayList<>( option.options() ), "/" ); + } + + /** + * Gives the option being considered when the exception was created. + * + * @return the option being considered when the exception was created + */ + public List<String> options() { + return unmodifiableList( options ); + } + + protected final String singleOptionString() { + return singleOptionString( options.get( 0 ) ); + } + + protected final String singleOptionString( String option ) { + return option; + } + + protected final String multipleOptionString() { + StringBuilder buffer = new StringBuilder( "[" ); + + Set<String> asSet = new LinkedHashSet<String>( options ); + for ( Iterator<String> iter = asSet.iterator(); iter.hasNext(); ) { + buffer.append( singleOptionString(iter.next()) ); + if ( iter.hasNext() ) + buffer.append( ", " ); + } + + buffer.append( ']' ); + + return buffer.toString(); + } + + static OptionException unrecognizedOption( String option ) { + return new UnrecognizedOptionException( option ); + } + + @Override + public final String getMessage() { + return localizedMessage( Locale.getDefault() ); + } + + final String localizedMessage( Locale locale ) { + return formattedMessage( locale ); + } + + private String formattedMessage( Locale locale ) { + return message( locale, "joptsimple.ExceptionMessages", getClass(), "message", messageArguments() ); + } + + abstract Object[] messageArguments(); +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/OptionMissingRequiredArgumentException.java b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionMissingRequiredArgumentException.java new file mode 100644 index 0000000000..9c69f12369 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionMissingRequiredArgumentException.java @@ -0,0 +1,46 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Arrays.*; + +/** + * Thrown when the option parser discovers options that require an argument, but are missing an argument. + * + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +class OptionMissingRequiredArgumentException extends OptionException { + private static final long serialVersionUID = -1L; + + OptionMissingRequiredArgumentException( OptionSpec<?> option ) { + super( asList( option ) ); + } + + @Override + Object[] messageArguments() { + return new Object[] { singleOptionString() }; + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/OptionParser.java b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionParser.java new file mode 100644 index 0000000000..d141f623c0 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionParser.java @@ -0,0 +1,647 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.*; + +import joptsimple.internal.AbbreviationMap; +import joptsimple.internal.SimpleOptionNameMap; +import joptsimple.internal.OptionNameMap; +import joptsimple.util.KeyValuePair; + +import static java.util.Collections.*; +import static joptsimple.OptionException.*; +import static joptsimple.OptionParserState.*; +import static joptsimple.ParserRules.*; + +/** + * <p>Parses command line arguments, using a syntax that attempts to take from the best of POSIX {@code getopt()} + * and GNU {@code getopt_long()}.</p> + * + * <p>This parser supports short options and long options.</p> + * + * <ul> + * <li><dfn>Short options</dfn> begin with a single hyphen ("{@code -}") followed by a single letter or digit, + * or question mark ("{@code ?}"), or dot ("{@code .}"), or underscore ("{@code _}").</li> + * + * <li>Short options can accept single arguments. The argument can be made required or optional. The option's + * argument can occur: + * <ul> + * <li>in the slot after the option, as in {@code -d /tmp}</li> + * <li>right up against the option, as in {@code -d/tmp}</li> + * <li>right up against the option separated by an equals sign ({@code "="}), as in {@code -d=/tmp}</li> + * </ul> + * To specify <em>n</em> arguments for an option, specify the option <em>n</em> times, once for each argument, + * as in {@code -d /tmp -d /var -d /opt}; or, when using the + * {@linkplain ArgumentAcceptingOptionSpec#withValuesSeparatedBy(char) "separated values"} clause of the "fluent + * interface" (see below), give multiple values separated by a given character as a single argument to the + * option.</li> + * + * <li>Short options can be clustered, so that {@code -abc} is treated as {@code -a -b -c}. If a short option + * in the cluster can accept an argument, the remaining characters are interpreted as the argument for that + * option.</li> + * + * <li>An argument consisting only of two hyphens ({@code "--"}) signals that the remaining arguments are to be + * treated as non-options.</li> + * + * <li>An argument consisting only of a single hyphen is considered a non-option argument (though it can be an + * argument of an option). Many Unix programs treat single hyphens as stand-ins for the standard input or standard + * output streams.</li> + * + * <li><dfn>Long options</dfn> begin with two hyphens ({@code "--"}), followed by multiple letters, digits, + * hyphens, question marks, or dots. A hyphen cannot be the first character of a long option specification when + * configuring the parser.</li> + * + * <li>You can abbreviate long options, so long as the abbreviation is unique. Suppress this behavior if + * you wish using {@linkplain OptionParser#OptionParser(boolean) this constructor}.</li> + * + * <li>Long options can accept single arguments. The argument can be made required or optional. The option's + * argument can occur: + * <ul> + * <li>in the slot after the option, as in {@code --directory /tmp}</li> + * <li>right up against the option separated by an equals sign ({@code "="}), as in + * {@code --directory=/tmp} + * </ul> + * Specify multiple arguments for a long option in the same manner as for short options (see above).</li> + * + * <li>You can use a single hyphen ({@code "-"}) instead of a double hyphen ({@code "--"}) for a long + * option.</li> + * + * <li>The option {@code -W} is reserved. If you tell the parser to {@linkplain + * #recognizeAlternativeLongOptions(boolean) recognize alternative long options}, then it will treat, for example, + * {@code -W foo=bar} as the long option {@code foo} with argument {@code bar}, as though you had written + * {@code --foo=bar}.</li> + * + * <li>You can specify {@code -W} as a valid short option, or use it as an abbreviation for a long option, but + * {@linkplain #recognizeAlternativeLongOptions(boolean) recognizing alternative long options} will always supersede + * this behavior.</li> + * + * <li>You can specify a given short or long option multiple times on a single command line. The parser collects + * any arguments specified for those options as a list.</li> + * + * <li>If the parser detects an option whose argument is optional, and the next argument "looks like" an option, + * that argument is not treated as the argument to the option, but as a potentially valid option. If, on the other + * hand, the optional argument is typed as a derivative of {@link Number}, then that argument is treated as the + * negative number argument of the option, even if the parser recognizes the corresponding numeric option. + * For example: + * <pre><code> + * OptionParser parser = new OptionParser(); + * parser.accepts( "a" ).withOptionalArg().ofType( Integer.class ); + * parser.accepts( "2" ); + * OptionSet options = parser.parse( "-a", "-2" ); + * </code></pre> + * In this case, the option set contains {@code "a"} with argument {@code -2}, not both {@code "a"} and + * {@code "2"}. Swapping the elements in the <em>args</em> array gives the latter.</li> + * </ul> + * + * <p>There are two ways to tell the parser what options to recognize:</p> + * + * <ol> + * <li>A "fluent interface"-style API for specifying options, available since version 2. Sentences in this fluent + * interface language begin with a call to {@link #accepts(String) accepts} or {@link #acceptsAll(List) + * acceptsAll} methods; calls on the ensuing chain of objects describe whether the options can take an argument, + * whether the argument is required or optional, to what type arguments of the options should be converted if any, + * etc. Since version 3, these calls return an instance of {@link OptionSpec}, which can subsequently be used to + * retrieve the arguments of the associated option in a type-safe manner.</li> + * + * <li>Since version 1, a more concise way of specifying short options has been to use the special {@linkplain + * #OptionParser(String) constructor}. Arguments of options specified in this manner will be of type {@link String}. + * Here are the rules for the format of the specification strings this constructor accepts: + * + * <ul> + * <li>Any letter or digit is treated as an option character.</li> + * + * <li>An option character can be immediately followed by an asterisk ({@code *)} to indicate that + * the option is a "help" option.</li> + * + * <li>If an option character (with possible trailing asterisk) is followed by a single colon ({@code ":"}), + * then the option requires an argument.</li> + * + * <li>If an option character (with possible trailing asterisk) is followed by two colons ({@code "::"}), + * then the option accepts an optional argument.</li> + * + * <li>Otherwise, the option character accepts no argument.</li> + * + * <li>If the option specification string begins with a plus sign ({@code "+" }), the parser will behave + * "POSIX-ly correct".</li> + * + * <li>If the option specification string contains the sequence {@code "W;"} (capital W followed by a + * semicolon), the parser will recognize the alternative form of long options.</li> + * </ul> + * </li> + * </ol> + * + * <p>Each of the options in a list of options given to {@link #acceptsAll(List) acceptsAll} is treated as a + * synonym of the others. For example:</p> + * <pre> + * <code> + * OptionParser parser = new OptionParser(); + * parser.acceptsAll( asList( "w", "interactive", "confirmation" ) ); + * OptionSet options = parser.parse( "-w" ); + * </code> + * </pre> + * <p>In this case, <code>options.{@link OptionSet#has(String) has}</code> would answer {@code true} when given arguments + * {@code "w"}, {@code "interactive"}, and {@code "confirmation"}. The {@link OptionSet} would give the same + * responses to these arguments for its other methods as well.</p> + * + * <p>By default, as with GNU {@code getopt()}, the parser allows intermixing of options and non-options. If, however, + * the parser has been created to be "POSIX-ly correct", then the first argument that does not look lexically like an + * option, and is not a required argument of a preceding option, signals the end of options. You can still bind + * optional arguments to their options using the abutting (for short options) or {@code =} syntax.</p> + * + * <p>Unlike GNU {@code getopt()}, this parser does not honor the environment variable {@code POSIXLY_CORRECT}. + * "POSIX-ly correct" parsers are configured by either:</p> + * + * <ol> + * <li>using the method {@link #posixlyCorrect(boolean)}, or</li> + * + * <li>using the {@linkplain #OptionParser(String) constructor} with an argument whose first character is a plus sign + * ({@code "+"})</li> + * </ol> + * + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + * @see <a href="http://www.gnu.org/software/libc/manual">The GNU C Library</a> + */ +public class OptionParser implements OptionDeclarer { + private final OptionNameMap<AbstractOptionSpec<?>> recognizedOptions; + private final ArrayList<AbstractOptionSpec<?>> trainingOrder; + private final Map<List<String>, Set<OptionSpec<?>>> requiredIf; + private final Map<List<String>, Set<OptionSpec<?>>> requiredUnless; + private final Map<List<String>, Set<OptionSpec<?>>> availableIf; + private final Map<List<String>, Set<OptionSpec<?>>> availableUnless; + + private OptionParserState state; + private boolean posixlyCorrect; + private boolean allowsUnrecognizedOptions; + private HelpFormatter helpFormatter = new BuiltinHelpFormatter(); + + /** + * Creates an option parser that initially recognizes no options, and does not exhibit "POSIX-ly correct" + * behavior. + */ + public OptionParser() { + this(true); + } + + /** + * Creates an option parser that initially recognizes no options, and does not exhibit "POSIX-ly correct" + * behavior. + * + * @param allowAbbreviations whether unambiguous abbreviations of long options should be recognized + * by the parser + */ + public OptionParser( boolean allowAbbreviations ) { + trainingOrder = new ArrayList<>(); + requiredIf = new HashMap<>(); + requiredUnless = new HashMap<>(); + availableIf = new HashMap<>(); + availableUnless = new HashMap<>(); + state = moreOptions( false ); + + recognizedOptions = allowAbbreviations + ? new AbbreviationMap<AbstractOptionSpec<?>>() + : new SimpleOptionNameMap<AbstractOptionSpec<?>>(); + + recognize( new NonOptionArgumentSpec<String>() ); + } + + /** + * Creates an option parser and configures it to recognize the short options specified in the given string. + * + * Arguments of options specified this way will be of type {@link String}. + * + * @param optionSpecification an option specification + * @throws NullPointerException if {@code optionSpecification} is {@code null} + * @throws OptionException if the option specification contains illegal characters or otherwise cannot be + * recognized + */ + public OptionParser( String optionSpecification ) { + this(); + + new OptionSpecTokenizer( optionSpecification ).configure( this ); + } + + public OptionSpecBuilder accepts( String option ) { + return acceptsAll( singletonList( option ) ); + } + + public OptionSpecBuilder accepts( String option, String description ) { + return acceptsAll( singletonList( option ), description ); + } + + public OptionSpecBuilder acceptsAll( List<String> options ) { + return acceptsAll( options, "" ); + } + + public OptionSpecBuilder acceptsAll( List<String> options, String description ) { + if ( options.isEmpty() ) + throw new IllegalArgumentException( "need at least one option" ); + + ensureLegalOptions( options ); + + return new OptionSpecBuilder( this, options, description ); + } + + public NonOptionArgumentSpec<String> nonOptions() { + NonOptionArgumentSpec<String> spec = new NonOptionArgumentSpec<>(); + + recognize( spec ); + + return spec; + } + + public NonOptionArgumentSpec<String> nonOptions( String description ) { + NonOptionArgumentSpec<String> spec = new NonOptionArgumentSpec<>( description ); + + recognize( spec ); + + return spec; + } + + public void posixlyCorrect( boolean setting ) { + posixlyCorrect = setting; + state = moreOptions( setting ); + } + + boolean posixlyCorrect() { + return posixlyCorrect; + } + + public void allowsUnrecognizedOptions() { + allowsUnrecognizedOptions = true; + } + + boolean doesAllowsUnrecognizedOptions() { + return allowsUnrecognizedOptions; + } + + public void recognizeAlternativeLongOptions( boolean recognize ) { + if ( recognize ) + recognize( new AlternativeLongOptionSpec() ); + else + recognizedOptions.remove( String.valueOf( RESERVED_FOR_EXTENSIONS ) ); + } + + void recognize( AbstractOptionSpec<?> spec ) { + recognizedOptions.putAll( spec.options(), spec ); + trainingOrder.add( spec ); + } + + /** + * Writes information about the options this parser recognizes to the given output sink. + * + * The output sink is flushed, but not closed. + * + * @param sink the sink to write information to + * @throws IOException if there is a problem writing to the sink + * @throws NullPointerException if {@code sink} is {@code null} + * @see #printHelpOn(Writer) + */ + public void printHelpOn( OutputStream sink ) throws IOException { + printHelpOn( new OutputStreamWriter( sink ) ); + } + + /** + * Writes information about the options this parser recognizes to the given output sink. + * + * The output sink is flushed, but not closed. + * + * @param sink the sink to write information to + * @throws IOException if there is a problem writing to the sink + * @throws NullPointerException if {@code sink} is {@code null} + * @see #printHelpOn(OutputStream) + */ + public void printHelpOn( Writer sink ) throws IOException { + sink.write( helpFormatter.format( _recognizedOptions() ) ); + sink.flush(); + } + + /** + * Tells the parser to use the given formatter when asked to {@linkplain #printHelpOn(java.io.Writer) print help}. + * + * @param formatter the formatter to use for printing help + * @throws NullPointerException if the formatter is {@code null} + */ + public void formatHelpWith( HelpFormatter formatter ) { + if ( formatter == null ) + throw new NullPointerException(); + + helpFormatter = formatter; + } + + /** + * Retrieves all options-spec pairings which have been configured for the parser in the same order as declared + * during training. Option flags for specs are alphabetized by {@link OptionSpec#options()}; only the order of the + * specs is preserved. + * + * (Note: prior to 4.7 the order was alphabetical across all options regardless of spec.) + * + * @return a map containing all the configured options and their corresponding {@link OptionSpec} + * @since 4.6 + */ + public Map<String, OptionSpec<?>> recognizedOptions() { + return new LinkedHashMap<String, OptionSpec<?>>( _recognizedOptions() ); + } + + private Map<String, AbstractOptionSpec<?>> _recognizedOptions() { + Map<String, AbstractOptionSpec<?>> options = new LinkedHashMap<>(); + for ( AbstractOptionSpec<?> spec : trainingOrder ) { + for ( String option : spec.options() ) + options.put( option, spec ); + } + return options; + } + + /** + * Parses the given command line arguments according to the option specifications given to the parser. + * + * @param arguments arguments to parse + * @return an {@link OptionSet} describing the parsed options, their arguments, and any non-option arguments found + * @throws OptionException if problems are detected while parsing + * @throws NullPointerException if the argument list is {@code null} + */ + public OptionSet parse( String... arguments ) { + ArgumentList argumentList = new ArgumentList( arguments ); + OptionSet detected = new OptionSet( recognizedOptions.toJavaUtilMap() ); + detected.add( recognizedOptions.get( NonOptionArgumentSpec.NAME ) ); + + while ( argumentList.hasMore() ) + state.handleArgument( this, argumentList, detected ); + + reset(); + + ensureRequiredOptions( detected ); + ensureAllowedOptions( detected ); + + return detected; + } + + /** + * Mandates mutual exclusiveness for the options built by the specified builders. + * + * @param specs descriptors for options that should be mutually exclusive on a command line. + * @throws NullPointerException if {@code specs} is {@code null} + */ + public void mutuallyExclusive( OptionSpecBuilder... specs ) { + for ( int i = 0; i < specs.length; i++ ) { + for ( int j = 0; j < specs.length; j++ ) { + if ( i != j ) + specs[i].availableUnless( specs[j] ); + } + } + } + + private void ensureRequiredOptions( OptionSet options ) { + List<AbstractOptionSpec<?>> missingRequiredOptions = missingRequiredOptions(options); + boolean helpOptionPresent = isHelpOptionPresent( options ); + + if ( !missingRequiredOptions.isEmpty() && !helpOptionPresent ) + throw new MissingRequiredOptionsException( missingRequiredOptions ); + } + + private void ensureAllowedOptions( OptionSet options ) { + List<AbstractOptionSpec<?>> forbiddenOptions = unavailableOptions( options ); + boolean helpOptionPresent = isHelpOptionPresent( options ); + + if ( !forbiddenOptions.isEmpty() && !helpOptionPresent ) + throw new UnavailableOptionException( forbiddenOptions ); + } + + private List<AbstractOptionSpec<?>> missingRequiredOptions( OptionSet options ) { + List<AbstractOptionSpec<?>> missingRequiredOptions = new ArrayList<>(); + + for ( AbstractOptionSpec<?> each : recognizedOptions.toJavaUtilMap().values() ) { + if ( each.isRequired() && !options.has( each ) ) + missingRequiredOptions.add(each); + } + + for ( Map.Entry<List<String>, Set<OptionSpec<?>>> each : requiredIf.entrySet() ) { + AbstractOptionSpec<?> required = specFor( each.getKey().iterator().next() ); + + if ( optionsHasAnyOf( options, each.getValue() ) && !options.has( required ) ) + missingRequiredOptions.add( required ); + } + + for ( Map.Entry<List<String>, Set<OptionSpec<?>>> each : requiredUnless.entrySet() ) { + AbstractOptionSpec<?> required = specFor(each.getKey().iterator().next()); + + if ( !optionsHasAnyOf( options, each.getValue() ) && !options.has( required ) ) + missingRequiredOptions.add( required ); + } + + return missingRequiredOptions; + } + + private List<AbstractOptionSpec<?>> unavailableOptions(OptionSet options) { + List<AbstractOptionSpec<?>> unavailableOptions = new ArrayList<>(); + + for ( Map.Entry<List<String>, Set<OptionSpec<?>>> eachEntry : availableIf.entrySet() ) { + AbstractOptionSpec<?> forbidden = specFor( eachEntry.getKey().iterator().next() ); + + if ( !optionsHasAnyOf( options, eachEntry.getValue() ) && options.has( forbidden ) ) { + unavailableOptions.add(forbidden); + } + } + + for ( Map.Entry<List<String>, Set<OptionSpec<?>>> eachEntry : availableUnless.entrySet() ) { + AbstractOptionSpec<?> forbidden = specFor( eachEntry.getKey().iterator().next() ); + + if ( optionsHasAnyOf( options, eachEntry.getValue() ) && options.has( forbidden ) ) { + unavailableOptions.add(forbidden); + } + } + + return unavailableOptions; + } + + private boolean optionsHasAnyOf( OptionSet options, Collection<OptionSpec<?>> specs ) { + for ( OptionSpec<?> each : specs ) { + if ( options.has( each ) ) + return true; + } + + return false; + } + + private boolean isHelpOptionPresent( OptionSet options ) { + boolean helpOptionPresent = false; + + for ( AbstractOptionSpec<?> each : recognizedOptions.toJavaUtilMap().values() ) { + if ( each.isForHelp() && options.has( each ) ) { + helpOptionPresent = true; + break; + } + } + + return helpOptionPresent; + } + + void handleLongOptionToken( String candidate, ArgumentList arguments, OptionSet detected ) { + KeyValuePair optionAndArgument = parseLongOptionWithArgument( candidate ); + + if ( !isRecognized( optionAndArgument.key ) ) + throw unrecognizedOption( optionAndArgument.key ); + + AbstractOptionSpec<?> optionSpec = specFor( optionAndArgument.key ); + optionSpec.handleOption( this, arguments, detected, optionAndArgument.value ); + } + + void handleShortOptionToken( String candidate, ArgumentList arguments, OptionSet detected ) { + KeyValuePair optionAndArgument = parseShortOptionWithArgument( candidate ); + + if ( isRecognized( optionAndArgument.key ) ) { + specFor( optionAndArgument.key ).handleOption( this, arguments, detected, optionAndArgument.value ); + } + else + handleShortOptionCluster( candidate, arguments, detected ); + } + + private void handleShortOptionCluster( String candidate, ArgumentList arguments, OptionSet detected ) { + char[] options = extractShortOptionsFrom( candidate ); + validateOptionCharacters( options ); + + for ( int i = 0; i < options.length; i++ ) { + AbstractOptionSpec<?> optionSpec = specFor( options[ i ] ); + + if ( optionSpec.acceptsArguments() && options.length > i + 1 ) { + String detectedArgument = String.valueOf( options, i + 1, options.length - 1 - i ); + optionSpec.handleOption( this, arguments, detected, detectedArgument ); + break; + } + + optionSpec.handleOption( this, arguments, detected, null ); + } + } + + void handleNonOptionArgument( String candidate, ArgumentList arguments, OptionSet detectedOptions ) { + specFor( NonOptionArgumentSpec.NAME ).handleOption( this, arguments, detectedOptions, candidate ); + } + + void noMoreOptions() { + state = OptionParserState.noMoreOptions(); + } + + boolean looksLikeAnOption( String argument ) { + return isShortOptionToken( argument ) || isLongOptionToken( argument ); + } + + boolean isRecognized( String option ) { + return recognizedOptions.contains( option ); + } + + void requiredIf( List<String> precedentSynonyms, String required ) { + requiredIf( precedentSynonyms, specFor( required ) ); + } + + void requiredIf( List<String> precedentSynonyms, OptionSpec<?> required ) { + putDependentOption( precedentSynonyms, required, requiredIf ); + } + + void requiredUnless( List<String> precedentSynonyms, String required ) { + requiredUnless( precedentSynonyms, specFor( required ) ); + } + + void requiredUnless( List<String> precedentSynonyms, OptionSpec<?> required ) { + putDependentOption( precedentSynonyms, required, requiredUnless ); + } + + void availableIf( List<String> precedentSynonyms, String available ) { + availableIf( precedentSynonyms, specFor( available ) ); + } + + void availableIf( List<String> precedentSynonyms, OptionSpec<?> available) { + putDependentOption( precedentSynonyms, available, availableIf ); + } + + void availableUnless( List<String> precedentSynonyms, String available ) { + availableUnless( precedentSynonyms, specFor( available ) ); + } + + void availableUnless( List<String> precedentSynonyms, OptionSpec<?> available ) { + putDependentOption( precedentSynonyms, available, availableUnless ); + } + + private void putDependentOption( List<String> precedentSynonyms, OptionSpec<?> required, + Map<List<String>, Set<OptionSpec<?>>> target ) { + + for ( String each : precedentSynonyms ) { + AbstractOptionSpec<?> spec = specFor( each ); + if ( spec == null ) + throw new UnconfiguredOptionException( precedentSynonyms ); + } + + Set<OptionSpec<?>> associated = target.get( precedentSynonyms ); + if ( associated == null ) { + associated = new HashSet<>(); + target.put( precedentSynonyms, associated ); + } + + associated.add( required ); + } + + private AbstractOptionSpec<?> specFor( char option ) { + return specFor( String.valueOf( option ) ); + } + + private AbstractOptionSpec<?> specFor( String option ) { + return recognizedOptions.get( option ); + } + + private void reset() { + state = moreOptions( posixlyCorrect ); + } + + private static char[] extractShortOptionsFrom( String argument ) { + char[] options = new char[ argument.length() - 1 ]; + argument.getChars( 1, argument.length(), options, 0 ); + + return options; + } + + private void validateOptionCharacters( char[] options ) { + for ( char each : options ) { + String option = String.valueOf( each ); + + if ( !isRecognized( option ) ) + throw unrecognizedOption( option ); + + if ( specFor( option ).acceptsArguments() ) + return; + } + } + + private static KeyValuePair parseLongOptionWithArgument( String argument ) { + return KeyValuePair.valueOf( argument.substring( 2 ) ); + } + + private static KeyValuePair parseShortOptionWithArgument( String argument ) { + return KeyValuePair.valueOf( argument.substring( 1 ) ); + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/OptionParserState.java b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionParserState.java new file mode 100644 index 0000000000..fe1000c263 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionParserState.java @@ -0,0 +1,76 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static joptsimple.ParserRules.*; + +/** + * Abstraction of parser state; mostly serves to model how a parser behaves depending on whether end-of-options + * has been detected. + * + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +abstract class OptionParserState { + static OptionParserState noMoreOptions() { + return new OptionParserState() { + @Override + protected void handleArgument( OptionParser parser, ArgumentList arguments, OptionSet detectedOptions ) { + parser.handleNonOptionArgument( arguments.next(), arguments, detectedOptions ); + } + }; + } + + static OptionParserState moreOptions( final boolean posixlyCorrect ) { + return new OptionParserState() { + @Override + protected void handleArgument( OptionParser parser, ArgumentList arguments, OptionSet detectedOptions ) { + String candidate = arguments.next(); + try { + if ( isOptionTerminator( candidate ) ) { + parser.noMoreOptions(); + return; + } else if ( isLongOptionToken( candidate ) ) { + parser.handleLongOptionToken( candidate, arguments, detectedOptions ); + return; + } else if ( isShortOptionToken( candidate ) ) { + parser.handleShortOptionToken( candidate, arguments, detectedOptions ); + return; + } + } catch ( UnrecognizedOptionException e ) { + if ( !parser.doesAllowsUnrecognizedOptions() ) + throw e; + } + + if ( posixlyCorrect ) + parser.noMoreOptions(); + + parser.handleNonOptionArgument( candidate, arguments, detectedOptions ); + } + }; + } + + protected abstract void handleArgument( OptionParser parser, ArgumentList arguments, OptionSet detectedOptions ); +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/OptionSet.java b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionSet.java new file mode 100644 index 0000000000..e67363fd2e --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionSet.java @@ -0,0 +1,325 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; + +import static java.util.Collections.*; +import static java.util.Objects.*; + +/** + * Representation of a group of detected command line options, their arguments, and non-option arguments. + * + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class OptionSet { + private final List<OptionSpec<?>> detectedSpecs; + private final Map<String, AbstractOptionSpec<?>> detectedOptions; + private final Map<AbstractOptionSpec<?>, List<String>> optionsToArguments; + private final Map<String, AbstractOptionSpec<?>> recognizedSpecs; + private final Map<String, List<?>> defaultValues; + + /* + * Package-private because clients don't create these. + */ + OptionSet( Map<String, AbstractOptionSpec<?>> recognizedSpecs ) { + detectedSpecs = new ArrayList<>(); + detectedOptions = new HashMap<>(); + optionsToArguments = new IdentityHashMap<>(); + defaultValues = defaultValues( recognizedSpecs ); + this.recognizedSpecs = recognizedSpecs; + } + + /** + * Tells whether any options were detected. + * + * @return {@code true} if any options were detected + */ + public boolean hasOptions() { + return !( detectedOptions.size() == 1 && detectedOptions.values().iterator().next().representsNonOptions() ); + } + + /** + * Tells whether the given option was detected. + * + * @param option the option to search for + * @return {@code true} if the option was detected + * @see #has(OptionSpec) + */ + public boolean has( String option ) { + return detectedOptions.containsKey( option ); + } + + /** + * Tells whether the given option was detected. + * + * <p>This method recognizes only instances of options returned from the fluent interface methods.</p> + * + * <p>Specifying a {@linkplain ArgumentAcceptingOptionSpec#defaultsTo(Object, Object[])} default argument value} + * for an option does not cause this method to return {@code true} if the option was not detected on the command + * line.</p> + * + * @param option the option to search for + * @return {@code true} if the option was detected + * @see #has(String) + */ + public boolean has( OptionSpec<?> option ) { + return optionsToArguments.containsKey( option ); + } + + /** + * Tells whether there are any arguments associated with the given option. + * + * @param option the option to search for + * @return {@code true} if the option was detected and at least one argument was detected for the option + * @see #hasArgument(OptionSpec) + */ + public boolean hasArgument( String option ) { + AbstractOptionSpec<?> spec = detectedOptions.get( option ); + return spec != null && hasArgument( spec ); + } + + /** + * Tells whether there are any arguments associated with the given option. + * + * <p>This method recognizes only instances of options returned from the fluent interface methods.</p> + * + * <p>Specifying a {@linkplain ArgumentAcceptingOptionSpec#defaultsTo(Object, Object[]) default argument value} + * for an option does not cause this method to return {@code true} if the option was not detected on the command + * line, or if the option can take an optional argument but did not have one on the command line.</p> + * + * @param option the option to search for + * @return {@code true} if the option was detected and at least one argument was detected for the option + * @throws NullPointerException if {@code option} is {@code null} + * @see #hasArgument(String) + */ + public boolean hasArgument( OptionSpec<?> option ) { + requireNonNull( option ); + + List<String> values = optionsToArguments.get( option ); + return values != null && !values.isEmpty(); + } + + /** + * Gives the argument associated with the given option. If the option was given an argument type, the argument + * will take on that type; otherwise, it will be a {@link String}. + * + * <p>Specifying a {@linkplain ArgumentAcceptingOptionSpec#defaultsTo(Object, Object[]) default argument value} + * for an option will cause this method to return that default value even if the option was not detected on the + * command line, or if the option can take an optional argument but did not have one on the command line.</p> + * + * @param option the option to search for + * @return the argument of the given option; {@code null} if no argument is present, or that option was not + * detected + * @throws NullPointerException if {@code option} is {@code null} + * @throws OptionException if more than one argument was detected for the option + */ + public Object valueOf( String option ) { + requireNonNull( option ); + + AbstractOptionSpec<?> spec = detectedOptions.get( option ); + if ( spec == null ) { + List<?> defaults = defaultValuesFor( option ); + return defaults.isEmpty() ? null : defaults.get( 0 ); + } + + return valueOf( spec ); + } + + /** + * Gives the argument associated with the given option. + * + * <p>This method recognizes only instances of options returned from the fluent interface methods.</p> + * + * @param <V> represents the type of the arguments the given option accepts + * @param option the option to search for + * @return the argument of the given option; {@code null} if no argument is present, or that option was not + * detected + * @throws OptionException if more than one argument was detected for the option + * @throws NullPointerException if {@code option} is {@code null} + * @throws ClassCastException if the arguments of this option are not of the expected type + */ + public <V> V valueOf( OptionSpec<V> option ) { + requireNonNull( option ); + + List<V> values = valuesOf( option ); + switch ( values.size() ) { + case 0: + return null; + case 1: + return values.get( 0 ); + default: + throw new MultipleArgumentsForOptionException( option ); + } + } + + /** + * <p>Gives any arguments associated with the given option. If the option was given an argument type, the + * arguments will take on that type; otherwise, they will be {@link String}s.</p> + * + * @param option the option to search for + * @return the arguments associated with the option, as a list of objects of the type given to the arguments; an + * empty list if no such arguments are present, or if the option was not detected + * @throws NullPointerException if {@code option} is {@code null} + */ + public List<?> valuesOf( String option ) { + requireNonNull( option ); + + AbstractOptionSpec<?> spec = detectedOptions.get( option ); + return spec == null ? defaultValuesFor( option ) : valuesOf( spec ); + } + + /** + * <p>Gives any arguments associated with the given option. If the option was given an argument type, the + * arguments will take on that type; otherwise, they will be {@link String}s.</p> + * + * <p>This method recognizes only instances of options returned from the fluent interface methods.</p> + * + * @param <V> represents the type of the arguments the given option accepts + * @param option the option to search for + * @return the arguments associated with the option; an empty list if no such arguments are present, or if the + * option was not detected + * @throws NullPointerException if {@code option} is {@code null} + * @throws OptionException if there is a problem converting the option's arguments to the desired type; for + * example, if the type does not implement a correct conversion constructor or method + */ + public <V> List<V> valuesOf( OptionSpec<V> option ) { + requireNonNull( option ); + + List<String> values = optionsToArguments.get( option ); + if ( values == null || values.isEmpty() ) + return defaultValueFor( option ); + + AbstractOptionSpec<V> spec = (AbstractOptionSpec<V>) option; + List<V> convertedValues = new ArrayList<>(); + for ( String each : values ) + convertedValues.add( spec.convert( each ) ); + + return unmodifiableList( convertedValues ); + } + + /** + * Gives the set of options that were detected, in the form of {@linkplain OptionSpec}s, in the order in which the + * options were found on the command line. + * + * @return the set of detected command line options + */ + public List<OptionSpec<?>> specs() { + List<OptionSpec<?>> specs = detectedSpecs; + specs.removeAll( singletonList( detectedOptions.get( NonOptionArgumentSpec.NAME ) ) ); + + return unmodifiableList( specs ); + } + + /** + * Gives all declared options as a map of string to {@linkplain OptionSpec}. + * + * @return the declared options as a map + */ + public Map<OptionSpec<?>, List<?>> asMap() { + Map<OptionSpec<?>, List<?>> map = new HashMap<>(); + + for ( AbstractOptionSpec<?> spec : recognizedSpecs.values() ) { + if ( !spec.representsNonOptions() ) + map.put( spec, valuesOf( spec ) ); + } + + return unmodifiableMap( map ); + } + + /** + * @return the detected non-option arguments + */ + public List<?> nonOptionArguments() { + AbstractOptionSpec<?> spec = detectedOptions.get( NonOptionArgumentSpec.NAME ); + return valuesOf( spec ); + } + + void add( AbstractOptionSpec<?> spec ) { + addWithArgument( spec, null ); + } + + void addWithArgument( AbstractOptionSpec<?> spec, String argument ) { + detectedSpecs.add( spec ); + + for ( String each : spec.options() ) + detectedOptions.put( each, spec ); + + List<String> optionArguments = optionsToArguments.get( spec ); + + if ( optionArguments == null ) { + optionArguments = new ArrayList<>(); + optionsToArguments.put( spec, optionArguments ); + } + + if ( argument != null ) + optionArguments.add( argument ); + } + + @Override + public boolean equals( Object that ) { + if ( this == that ) + return true; + + if ( that == null || !getClass().equals( that.getClass() ) ) + return false; + + OptionSet other = (OptionSet) that; + Map<AbstractOptionSpec<?>, List<String>> thisOptionsToArguments = new HashMap<>( optionsToArguments ); + Map<AbstractOptionSpec<?>, List<String>> otherOptionsToArguments = new HashMap<>( other.optionsToArguments ); + return detectedOptions.equals( other.detectedOptions ) + && thisOptionsToArguments.equals( otherOptionsToArguments ); + } + + @Override + public int hashCode() { + Map<AbstractOptionSpec<?>, List<String>> thisOptionsToArguments = new HashMap<>( optionsToArguments ); + return detectedOptions.hashCode() ^ thisOptionsToArguments.hashCode(); + } + + @SuppressWarnings( "unchecked" ) + private <V> List<V> defaultValuesFor( String option ) { + if ( defaultValues.containsKey( option ) ) + return unmodifiableList( (List<V>) defaultValues.get( option ) ); + + return emptyList(); + } + + private <V> List<V> defaultValueFor( OptionSpec<V> option ) { + return defaultValuesFor( option.options().iterator().next() ); + } + + private static Map<String, List<?>> defaultValues( Map<String, AbstractOptionSpec<?>> recognizedSpecs ) { + Map<String, List<?>> defaults = new HashMap<>(); + for ( Map.Entry<String, AbstractOptionSpec<?>> each : recognizedSpecs.entrySet() ) + defaults.put( each.getKey(), each.getValue().defaultValues() ); + return defaults; + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/OptionSpec.java b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionSpec.java new file mode 100644 index 0000000000..70d2d43072 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionSpec.java @@ -0,0 +1,97 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.List; + +/** + * Describes options that an option parser recognizes. + * + * <p>Instances of this interface are returned by the "fluent interface" methods to allow retrieval of option arguments + * in a type-safe manner. Here's an example:</p> + * + * <pre><code> + * OptionParser parser = new OptionParser(); + * <strong>OptionSpec<Integer></strong> count = + * parser.accepts( "count" ).withRequiredArg().ofType( Integer.class ); + * OptionSet options = parser.parse( "--count", "2" ); + * assert options.has( count ); + * int countValue = options.valueOf( count ); + * assert countValue == count.value( options ); + * List<Integer> countValues = options.valuesOf( count ); + * assert countValues.equals( count.values( options ) ); + * </code></pre> + * + * @param <V> represents the type of the arguments this option accepts + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public interface OptionSpec<V> { + /** + * Gives any arguments associated with the given option in the given set of detected options. + * + * <p>Specifying a {@linkplain ArgumentAcceptingOptionSpec#defaultsTo(Object, Object[]) default argument value} + * for this option will cause this method to return that default value even if this option was not detected on the + * command line, or if this option can take an optional argument but did not have one on the command line.</p> + * + * @param detectedOptions the detected options to search in + * @return the arguments associated with this option; an empty list if no such arguments are present, or if this + * option was not detected + * @throws OptionException if there is a problem converting this option's arguments to the desired type; for + * example, if the type does not implement a correct conversion constructor or method + * @throws NullPointerException if {@code detectedOptions} is {@code null} + * @see OptionSet#valuesOf(OptionSpec) + */ + List<V> values( OptionSet detectedOptions ); + + /** + * Gives the argument associated with the given option in the given set of detected options. + * + * <p>Specifying a {@linkplain ArgumentAcceptingOptionSpec#defaultsTo(Object, Object[]) default argument value} + * for this option will cause this method to return that default value even if this option was not detected on the + * command line, or if this option can take an optional argument but did not have one on the command line.</p> + * + * @param detectedOptions the detected options to search in + * @return the argument of the this option; {@code null} if no argument is present, or that option was not detected + * @throws OptionException if more than one argument was detected for the option + * @throws NullPointerException if {@code detectedOptions} is {@code null} + * @throws ClassCastException if the arguments of this option are not of the expected type + * @see OptionSet#valueOf(OptionSpec) + */ + V value( OptionSet detectedOptions ); + + /** + * @return the string representations of this option + */ + List<String> options(); + + /** + * Tells whether this option is designated as a "help" option. The presence of a "help" option on a command line + * means that missing "required" options will not cause parsing to fail. + * + * @return whether this option is designated as a "help" option + */ + boolean isForHelp(); +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/OptionSpecBuilder.java b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionSpecBuilder.java new file mode 100644 index 0000000000..fd5a15a1d6 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionSpecBuilder.java @@ -0,0 +1,275 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Allows callers to specify whether a given option accepts arguments (required or optional). + * + * <p>Instances are returned from {@link OptionParser#accepts(String)} to allow the formation of parser directives as + * sentences in a "fluent interface" language. For example:</p> + * + * <pre><code> + * OptionParser parser = new OptionParser(); + * parser.accepts( "c" ).<strong>withRequiredArg()</strong>.ofType( Integer.class ); + * </code></pre> + * + * <p>If no methods are invoked on an instance of this class, then that instance's option will accept no argument.</p> + * + * <p>Note that you should not use the fluent interface clauses in a way that would defeat the typing of option + * arguments:</p> + * + * <pre><code> + * OptionParser parser = new OptionParser(); + * ArgumentAcceptingOptionSpec<String> optionC = + * parser.accepts( "c" ).withRequiredArg(); + * <strong>optionC.ofType( Integer.class ); // DON'T THROW AWAY THE TYPE!</strong> + * + * String value = parser.parse( "-c", "2" ).valueOf( optionC ); // ClassCastException + * </code></pre> + * + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class OptionSpecBuilder extends NoArgumentOptionSpec { + private final OptionParser parser; + + OptionSpecBuilder( OptionParser parser, List<String> options, String description ) { + super( options, description ); + + this.parser = parser; + attachToParser(); + } + + private void attachToParser() { + parser.recognize( this ); + } + + /** + * Informs an option parser that this builder's option requires an argument. + * + * @return a specification for the option + */ + public ArgumentAcceptingOptionSpec<String> withRequiredArg() { + ArgumentAcceptingOptionSpec<String> newSpec = new RequiredArgumentOptionSpec<>( options(), description() ); + parser.recognize( newSpec ); + + return newSpec; + } + + /** + * Informs an option parser that this builder's option accepts an optional argument. + * + * @return a specification for the option + */ + public ArgumentAcceptingOptionSpec<String> withOptionalArg() { + ArgumentAcceptingOptionSpec<String> newSpec = + new OptionalArgumentOptionSpec<>( options(), description() ); + parser.recognize( newSpec ); + + return newSpec; + } + + /** + * <p>Informs an option parser that this builder's option is required if the given option is present on the command + * line.</p> + * + * <p>For a given option, you <em>should not</em> mix this with {@link #requiredUnless(String, String...) + * requiredUnless} to avoid conflicts.</p> + * + * @param dependent an option whose presence on a command line makes this builder's option required + * @param otherDependents other options whose presence on a command line makes this builder's option required + * @return self, so that the caller can add clauses to the fluent interface sentence + * @throws OptionException if any of the dependent options haven't been configured in the parser yet + */ + public OptionSpecBuilder requiredIf( String dependent, String... otherDependents ) { + List<String> dependents = validatedDependents( dependent, otherDependents ); + for ( String each : dependents ) + parser.requiredIf( options(), each ); + + return this; + } + + /** + * <p>Informs an option parser that this builder's option is required if the given option is present on the command + * line.</p> + * + * <p>For a given option, you <em>should not</em> mix this with {@link #requiredUnless(OptionSpec, OptionSpec[]) + * requiredUnless} to avoid conflicts.</p> + * + * <p>This method recognizes only instances of options returned from the fluent interface methods.</p> + * + * @param dependent the option whose presence on a command line makes this builder's option required + * @param otherDependents other options whose presence on a command line makes this builder's option required + * @return self, so that the caller can add clauses to the fluent interface sentence + */ + public OptionSpecBuilder requiredIf( OptionSpec<?> dependent, OptionSpec<?>... otherDependents ) { + parser.requiredIf( options(), dependent ); + for ( OptionSpec<?> each : otherDependents ) + parser.requiredIf( options(), each ); + + return this; + } + + /** + * <p>Informs an option parser that this builder's option is required if the given option is absent on the command + * line.</p> + * + * <p>For a given option, you <em>should not</em> mix this with {@link #requiredIf(OptionSpec, OptionSpec[]) + * requiredIf} to avoid conflicts.</p> + * + * @param dependent an option whose absence on a command line makes this builder's option required + * @param otherDependents other options whose absence on a command line makes this builder's option required + * @return self, so that the caller can add clauses to the fluent interface sentence + * @throws OptionException if any of the dependent options haven't been configured in the parser yet + */ + public OptionSpecBuilder requiredUnless( String dependent, String... otherDependents ) { + List<String> dependents = validatedDependents( dependent, otherDependents ); + for ( String each : dependents ) { + parser.requiredUnless( options(), each ); + } + return this; + } + + /** + * <p>Informs an option parser that this builder's option is required if the given option is absent on the command + * line.</p> + * + * <p>For a given option, you <em>should not</em> mix this with {@link #requiredIf(OptionSpec, OptionSpec[]) + * requiredIf} to avoid conflicts.</p> + * + * <p>This method recognizes only instances of options returned from the fluent interface methods.</p> + * + * @param dependent the option whose absence on a command line makes this builder's option required + * @param otherDependents other options whose absence on a command line makes this builder's option required + * @return self, so that the caller can add clauses to the fluent interface sentence + */ + public OptionSpecBuilder requiredUnless( OptionSpec<?> dependent, OptionSpec<?>... otherDependents ) { + parser.requiredUnless( options(), dependent ); + for ( OptionSpec<?> each : otherDependents ) + parser.requiredUnless( options(), each ); + + return this; + } + + /** + * <p>Informs an option parser that this builder's option is allowed if the given option is present on the command + * line.</p> + * + * <p>For a given option, you <em>should not</em> mix this with {@link #availableUnless(String, String...) + * availableUnless} to avoid conflicts.</p> + * + * @param dependent an option whose presence on a command line makes this builder's option allowed + * @param otherDependents other options whose presence on a command line makes this builder's option allowed + * @return self, so that the caller can add clauses to the fluent interface sentence + * @throws OptionException if any of the dependent options haven't been configured in the parser yet + */ + public OptionSpecBuilder availableIf( String dependent, String... otherDependents ) { + List<String> dependents = validatedDependents( dependent, otherDependents ); + for ( String each : dependents ) + parser.availableIf( options(), each ); + + return this; + } + + /** + * <p>Informs an option parser that this builder's option is allowed if the given option is present on the command + * line.</p> + * + * <p>For a given option, you <em>should not</em> mix this with {@link #availableUnless(OptionSpec, OptionSpec[]) + * requiredUnless} to avoid conflicts.</p> + * + * <p>This method recognizes only instances of options returned from the fluent interface methods.</p> + * + * @param dependent the option whose presence on a command line makes this builder's option allowed + * @param otherDependents other options whose presence on a command line makes this builder's option allowed + * @return self, so that the caller can add clauses to the fluent interface sentence + */ + public OptionSpecBuilder availableIf( OptionSpec<?> dependent, OptionSpec<?>... otherDependents ) { + parser.availableIf( options(), dependent ); + + for ( OptionSpec<?> each : otherDependents ) + parser.availableIf( options(), each ); + + return this; + } + + /** + * <p>Informs an option parser that this builder's option is allowed if the given option is absent on the command + * line.</p> + * + * <p>For a given option, you <em>should not</em> mix this with {@link #availableIf(OptionSpec, OptionSpec[]) + * requiredIf} to avoid conflicts.</p> + * + * @param dependent an option whose absence on a command line makes this builder's option allowed + * @param otherDependents other options whose absence on a command line makes this builder's option allowed + * @return self, so that the caller can add clauses to the fluent interface sentence + * @throws OptionException if any of the dependent options haven't been configured in the parser yet + */ + public OptionSpecBuilder availableUnless( String dependent, String... otherDependents ) { + List<String> dependents = validatedDependents( dependent, otherDependents ); + for ( String each : dependents ) + parser.availableUnless( options(), each ); + + return this; + } + + /** + * <p>Informs an option parser that this builder's option is allowed if the given option is absent on the command + * line.</p> + * + * <p>For a given option, you <em>should not</em> mix this with {@link #availableIf(OptionSpec, OptionSpec[]) + * requiredIf} to avoid conflicts.</p> + * + * <p>This method recognizes only instances of options returned from the fluent interface methods.</p> + * + * @param dependent the option whose absence on a command line makes this builder's option allowed + * @param otherDependents other options whose absence on a command line makes this builder's option allowed + * @return self, so that the caller can add clauses to the fluent interface sentence + */ + public OptionSpecBuilder availableUnless( OptionSpec<?> dependent, OptionSpec<?>... otherDependents ) { + parser.availableUnless( options(), dependent ); + for ( OptionSpec<?> each : otherDependents ) + parser.availableUnless(options(), each); + + return this; + } + + private List<String> validatedDependents( String dependent, String... otherDependents ) { + List<String> dependents = new ArrayList<>(); + dependents.add( dependent ); + Collections.addAll( dependents, otherDependents ); + + for ( String each : dependents ) { + if ( !parser.isRecognized( each ) ) + throw new UnconfiguredOptionException( each ); + } + + return dependents; + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/OptionSpecTokenizer.java b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionSpecTokenizer.java new file mode 100644 index 0000000000..f9e4606c0c --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionSpecTokenizer.java @@ -0,0 +1,126 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.NoSuchElementException; + +import static joptsimple.ParserRules.*; + +/** + * Tokenizes a short option specification string. + * + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +class OptionSpecTokenizer { + private static final char POSIXLY_CORRECT_MARKER = '+'; + private static final char HELP_MARKER = '*'; + + private String specification; + private int index; + + OptionSpecTokenizer( String specification ) { + if ( specification == null ) + throw new NullPointerException( "null option specification" ); + + this.specification = specification; + } + + boolean hasMore() { + return index < specification.length(); + } + + AbstractOptionSpec<?> next() { + if ( !hasMore() ) + throw new NoSuchElementException(); + + + String optionCandidate = String.valueOf( specification.charAt( index ) ); + index++; + + AbstractOptionSpec<?> spec; + if ( RESERVED_FOR_EXTENSIONS.equals( optionCandidate ) ) { + spec = handleReservedForExtensionsToken(); + + if ( spec != null ) + return spec; + } + + ensureLegalOption( optionCandidate ); + + if ( hasMore() ) { + boolean forHelp = false; + if ( specification.charAt( index ) == HELP_MARKER ) { + forHelp = true; + ++index; + } + spec = hasMore() && specification.charAt( index ) == ':' + ? handleArgumentAcceptingOption( optionCandidate ) + : new NoArgumentOptionSpec( optionCandidate ); + if ( forHelp ) + spec.forHelp(); + } else + spec = new NoArgumentOptionSpec( optionCandidate ); + + return spec; + } + + void configure( OptionParser parser ) { + adjustForPosixlyCorrect( parser ); + + while ( hasMore() ) + parser.recognize( next() ); + } + + private void adjustForPosixlyCorrect( OptionParser parser ) { + if ( POSIXLY_CORRECT_MARKER == specification.charAt( 0 ) ) { + parser.posixlyCorrect( true ); + specification = specification.substring( 1 ); + } + } + + private AbstractOptionSpec<?> handleReservedForExtensionsToken() { + if ( !hasMore() ) + return new NoArgumentOptionSpec( RESERVED_FOR_EXTENSIONS ); + + if ( specification.charAt( index ) == ';' ) { + ++index; + return new AlternativeLongOptionSpec(); + } + + return null; + } + + private AbstractOptionSpec<?> handleArgumentAcceptingOption( String candidate ) { + index++; + + if ( hasMore() && specification.charAt( index ) == ':' ) { + index++; + return new OptionalArgumentOptionSpec<String>( candidate ); + } + + return new RequiredArgumentOptionSpec<String>( candidate ); + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/OptionalArgumentOptionSpec.java b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionalArgumentOptionSpec.java new file mode 100644 index 0000000000..cd641ed580 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/OptionalArgumentOptionSpec.java @@ -0,0 +1,69 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.List; + +/** + * Specification of an option that accepts an optional argument. + * + * @param <V> represents the type of the arguments this option accepts + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +class OptionalArgumentOptionSpec<V> extends ArgumentAcceptingOptionSpec<V> { + OptionalArgumentOptionSpec( String option ) { + super( option, false ); + } + + OptionalArgumentOptionSpec( List<String> options, String description ) { + super( options, false, description ); + } + + @Override + protected void detectOptionArgument( OptionParser parser, ArgumentList arguments, OptionSet detectedOptions ) { + if ( arguments.hasMore() ) { + String nextArgument = arguments.peek(); + + if ( !parser.looksLikeAnOption( nextArgument ) && canConvertArgument( nextArgument ) ) + handleOptionArgument( parser, detectedOptions, arguments ); + else if ( isArgumentOfNumberType() && canConvertArgument( nextArgument ) ) + addArguments( detectedOptions, arguments.next() ); + else + detectedOptions.add( this ); + } + else + detectedOptions.add( this ); + } + + private void handleOptionArgument( OptionParser parser, OptionSet detectedOptions, ArgumentList arguments ) { + if ( parser.posixlyCorrect() ) { + detectedOptions.add( this ); + parser.noMoreOptions(); + } + else + addArguments( detectedOptions, arguments.next() ); + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/ParserRules.java b/third_party/java/jopt-simple/src/main/java/joptsimple/ParserRules.java new file mode 100644 index 0000000000..34ef7814d5 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/ParserRules.java @@ -0,0 +1,84 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.List; + +import static java.lang.Character.*; + +/** + * Can tell whether or not options are well-formed. + * + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +final class ParserRules { + static final char HYPHEN_CHAR = '-'; + static final String HYPHEN = String.valueOf( HYPHEN_CHAR ); + static final String DOUBLE_HYPHEN = "--"; + static final String OPTION_TERMINATOR = DOUBLE_HYPHEN; + static final String RESERVED_FOR_EXTENSIONS = "W"; + + private ParserRules() { + throw new UnsupportedOperationException(); + } + + static boolean isShortOptionToken( String argument ) { + return argument.startsWith( HYPHEN ) + && !HYPHEN.equals( argument ) + && !isLongOptionToken( argument ); + } + + static boolean isLongOptionToken( String argument ) { + return argument.startsWith( DOUBLE_HYPHEN ) && !isOptionTerminator( argument ); + } + + static boolean isOptionTerminator( String argument ) { + return OPTION_TERMINATOR.equals( argument ); + } + + static void ensureLegalOption( String option ) { + if ( option.startsWith( HYPHEN ) ) + throw new IllegalOptionSpecificationException( String.valueOf( option ) ); + + for ( int i = 0; i < option.length(); ++i ) + ensureLegalOptionCharacter( option.charAt( i ) ); + } + + static void ensureLegalOptions( List<String> options ) { + for ( String each : options ) + ensureLegalOption( each ); + } + + private static void ensureLegalOptionCharacter( char option ) { + if ( !( isLetterOrDigit( option ) || isAllowedPunctuation( option ) ) ) + throw new IllegalOptionSpecificationException( String.valueOf( option ) ); + } + + private static boolean isAllowedPunctuation( char option ) { + String allowedPunctuation = "?._" + HYPHEN_CHAR; + return allowedPunctuation.indexOf( option ) != -1; + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/RequiredArgumentOptionSpec.java b/third_party/java/jopt-simple/src/main/java/joptsimple/RequiredArgumentOptionSpec.java new file mode 100644 index 0000000000..4c7ab880c7 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/RequiredArgumentOptionSpec.java @@ -0,0 +1,52 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.List; + +/** + * Specification of an option that accepts a required argument. + * + * @param <V> represents the type of the arguments this option accepts + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +class RequiredArgumentOptionSpec<V> extends ArgumentAcceptingOptionSpec<V> { + RequiredArgumentOptionSpec( String option ) { + super( option, true ); + } + + RequiredArgumentOptionSpec( List<String> options, String description ) { + super( options, true, description ); + } + + @Override + protected void detectOptionArgument( OptionParser parser, ArgumentList arguments, OptionSet detectedOptions ) { + if ( !arguments.hasMore() ) + throw new OptionMissingRequiredArgumentException( this ); + + addArguments( detectedOptions, arguments.next() ); + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/UnavailableOptionException.java b/third_party/java/jopt-simple/src/main/java/joptsimple/UnavailableOptionException.java new file mode 100644 index 0000000000..b1fa0e3a1e --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/UnavailableOptionException.java @@ -0,0 +1,45 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.List; + +/** + * Thrown when options marked as allowed are specified on the command line, but the options they depend upon are + * present/not present. + */ +class UnavailableOptionException extends OptionException { + private static final long serialVersionUID = -1L; + + UnavailableOptionException( List<? extends OptionSpec<?>> forbiddenOptions ) { + super( forbiddenOptions ); + } + + @Override + Object[] messageArguments() { + return new Object[] { multipleOptionString() }; + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/UnconfiguredOptionException.java b/third_party/java/jopt-simple/src/main/java/joptsimple/UnconfiguredOptionException.java new file mode 100644 index 0000000000..f62d88bd4a --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/UnconfiguredOptionException.java @@ -0,0 +1,52 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.List; + +import static java.util.Collections.*; + +/** + * Thrown when an option parser refers to an option that is not in fact configured already on the parser. + * + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +class UnconfiguredOptionException extends OptionException { + private static final long serialVersionUID = -1L; + + UnconfiguredOptionException( String option ) { + this( singletonList( option ) ); + } + + UnconfiguredOptionException( List<String> options ) { + super( options ); + } + + @Override + Object[] messageArguments() { + return new Object[] { multipleOptionString() }; + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/UnrecognizedOptionException.java b/third_party/java/jopt-simple/src/main/java/joptsimple/UnrecognizedOptionException.java new file mode 100644 index 0000000000..73e7d74a0b --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/UnrecognizedOptionException.java @@ -0,0 +1,46 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Collections.*; + +/** + * Thrown when the option parser encounters an unrecognized option. + * + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +class UnrecognizedOptionException extends OptionException { + private static final long serialVersionUID = -1L; + + UnrecognizedOptionException( String option ) { + super( singletonList( option ) ); + } + + @Override + Object[] messageArguments() { + return new Object[] { singleOptionString() }; + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/ValueConversionException.java b/third_party/java/jopt-simple/src/main/java/joptsimple/ValueConversionException.java new file mode 100644 index 0000000000..50d575d194 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/ValueConversionException.java @@ -0,0 +1,54 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +/** + * Thrown by {@link ValueConverter}s when problems occur in converting string values to other Java types. + * + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class ValueConversionException extends RuntimeException { + private static final long serialVersionUID = -1L; + + /** + * Creates a new exception with the specified detail message. + * + * @param message the detail message + */ + public ValueConversionException( String message ) { + this( message, null ); + } + + /** + * Creates a new exception with the specified detail message and cause. + * + * @param message the detail message + * @param cause the original exception + */ + public ValueConversionException( String message, Throwable cause ) { + super( message, cause ); + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/ValueConverter.java b/third_party/java/jopt-simple/src/main/java/joptsimple/ValueConverter.java new file mode 100644 index 0000000000..bc968da2d8 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/ValueConverter.java @@ -0,0 +1,58 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +/** + * Instances of this interface are used to convert arguments of options into specific Java types. + * + * @param <V> constraint on the type of values being converted to + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public interface ValueConverter<V> { + /** + * Converts the given string value into a Java type. + * + * @param value the string to convert + * @return the converted value + * @throws ValueConversionException if a problem occurs while converting the value + */ + V convert( String value ); + + /** + * Gives the class of the type of values this converter converts to. + * + * @return the target class for conversion + */ + Class<? extends V> valueType(); + + /** + * Gives a string that describes the pattern of the values this converter expects, if any. For example, a date + * converter can respond with a {@link java.text.SimpleDateFormat date format string}. + * + * @return a value pattern, or {@code null} if there's nothing interesting here + */ + String valuePattern(); +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/internal/AbbreviationMap.java b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/AbbreviationMap.java new file mode 100644 index 0000000000..0d601839a5 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/AbbreviationMap.java @@ -0,0 +1,242 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.internal; + +import java.util.Map; +import java.util.TreeMap; + +/** + * <p>A map whose keys are strings; when a key/value pair is added to the map, the longest unique abbreviations of that + * key are added as well, and associated with the value. Thus:</p> + * + * <pre> + * <code> + * abbreviations.put( "good", "bye" ); + * </code> + * </pre> + * + * <p>would make it such that you could retrieve the value {@code "bye"} from the map using the keys {@code "good"}, + * {@code "goo"}, {@code "go"}, and {@code "g"}. A subsequent invocation of:</p> + * <pre> + * <code> + * abbreviations.put( "go", "fish" ); + * </code> + * </pre> + * + * <p>would make it such that you could retrieve the value {@code "bye"} using the keys {@code "good"} and + * {@code "goo"}, and the value {@code "fish"} using the key {@code "go"}. The key {@code "g"} would yield + * {@code null}, since it would no longer be a unique abbreviation.</p> + * + * <p>The data structure is much like a "trie".</p> + * + * @param <V> a constraint on the types of the values in the map + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + * @see <a href="http://perldoc.perl.org/Text/Abbrev.html">Perl's Text::Abbrev module</a> + * @see <a href="https://en.wikipedia.org/wiki/Radix_tree">Radix tree</a> + */ +public class AbbreviationMap<V> implements OptionNameMap<V> { + private final Map<Character, AbbreviationMap<V>> children = new TreeMap<>(); + + private String key; + private V value; + private int keysBeyond; + + /** + * <p>Tells whether the given key is in the map, or whether the given key is a unique + * abbreviation of a key that is in the map.</p> + * + * @param key key to look up + * @return {@code true} if {@code key} is present in the map + * @throws NullPointerException if {@code key} is {@code null} + */ + @Override + public boolean contains(String key) { + return get(key) != null; + } + + /** + * <p>Answers the value associated with the given key. The key can be a unique + * abbreviation of a key that is in the map. </p> + * + * @param key key to look up + * @return the value associated with {@code aKey}; or {@code null} if there is no + * such value or {@code aKey} is not a unique abbreviation of a key in the map + * @throws NullPointerException if {@code aKey} is {@code null} + */ + @Override + public V get( String key ) { + char[] chars = charsOf( key ); + + AbbreviationMap<V> child = this; + for ( char each : chars ) { + child = child.children.get( each ); + if ( child == null ) + return null; + } + + return child.value; + } + + /** + * <p>Associates a given value with a given key. If there was a previous + * association, the old value is replaced with the new one.</p> + * + * @param key key to create in the map + * @param newValue value to associate with the key + * @throws NullPointerException if {@code aKey} or {@code newValue} is {@code null} + * @throws IllegalArgumentException if {@code aKey} is a zero-length string + */ + @Override + public void put( String key, V newValue ) { + if ( newValue == null ) + throw new NullPointerException(); + if ( key.length() == 0 ) + throw new IllegalArgumentException(); + + char[] chars = charsOf(key); + add( chars, newValue, 0, chars.length ); + } + + /** + * <p>Associates a given value with a given set of keys. If there was a previous + * association, the old value is replaced with the new one.</p> + * + * @param keys keys to create in the map + * @param newValue value to associate with the key + * @throws NullPointerException if {@code keys} or {@code newValue} is {@code null} + * @throws IllegalArgumentException if any of {@code keys} is a zero-length string + */ + @Override + public void putAll( Iterable<String> keys, V newValue ) { + for ( String each : keys ) + put( each, newValue ); + } + + private boolean add( char[] chars, V newValue, int offset, int length ) { + if ( offset == length ) { + value = newValue; + boolean wasAlreadyAKey = key != null; + key = new String( chars ); + return !wasAlreadyAKey; + } + + char nextChar = chars[ offset ]; + AbbreviationMap<V> child = children.get( nextChar ); + if ( child == null ) { + child = new AbbreviationMap<>(); + children.put( nextChar, child ); + } + + boolean newKeyAdded = child.add( chars, newValue, offset + 1, length ); + + if ( newKeyAdded ) + ++keysBeyond; + + if ( key == null ) + value = keysBeyond > 1 ? null : newValue; + + return newKeyAdded; + } + + /** + * <p>If the map contains the given key, dissociates the key from its value.</p> + * + * @param key key to remove + * @throws NullPointerException if {@code aKey} is {@code null} + * @throws IllegalArgumentException if {@code aKey} is a zero-length string + */ + @Override + public void remove( String key ) { + if ( key.length() == 0 ) + throw new IllegalArgumentException(); + + char[] keyChars = charsOf(key); + remove( keyChars, 0, keyChars.length ); + } + + private boolean remove( char[] aKey, int offset, int length ) { + if ( offset == length ) + return removeAtEndOfKey(); + + char nextChar = aKey[ offset ]; + AbbreviationMap<V> child = children.get( nextChar ); + if ( child == null || !child.remove( aKey, offset + 1, length ) ) + return false; + + --keysBeyond; + if ( child.keysBeyond == 0 ) + children.remove( nextChar ); + if ( keysBeyond == 1 && key == null ) + setValueToThatOfOnlyChild(); + + return true; + } + + private void setValueToThatOfOnlyChild() { + Map.Entry<Character, AbbreviationMap<V>> entry = children.entrySet().iterator().next(); + AbbreviationMap<V> onlyChild = entry.getValue(); + value = onlyChild.value; + } + + private boolean removeAtEndOfKey() { + if ( key == null ) + return false; + + key = null; + if ( keysBeyond == 1 ) + setValueToThatOfOnlyChild(); + else + value = null; + + return true; + } + + /** + * Gives a Java map representation of this abbreviation map. + * + * @return a Java map corresponding to this abbreviation map + */ + @Override + public Map<String, V> toJavaUtilMap() { + Map<String, V> mappings = new TreeMap<>(); + addToMappings( mappings ); + return mappings; + } + + private void addToMappings( Map<String, V> mappings ) { + if ( key != null ) + mappings.put( key, value ); + + for ( AbbreviationMap<V> each : children.values() ) + each.addToMappings( mappings ); + } + + private static char[] charsOf( String aKey ) { + char[] chars = new char[ aKey.length() ]; + aKey.getChars( 0, aKey.length(), chars, 0 ); + return chars; + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Classes.java b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Classes.java new file mode 100644 index 0000000000..f7030f88cb --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Classes.java @@ -0,0 +1,75 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.internal; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public final class Classes { + private static final Map<Class<?>, Class<?>> WRAPPERS = new HashMap<>( 13 ); + + static { + WRAPPERS.put( boolean.class, Boolean.class ); + WRAPPERS.put( byte.class, Byte.class ); + WRAPPERS.put( char.class, Character.class ); + WRAPPERS.put( double.class, Double.class ); + WRAPPERS.put( float.class, Float.class ); + WRAPPERS.put( int.class, Integer.class ); + WRAPPERS.put( long.class, Long.class ); + WRAPPERS.put( short.class, Short.class ); + WRAPPERS.put( void.class, Void.class ); + } + + private Classes() { + throw new UnsupportedOperationException(); + } + + /** + * Gives the "short version" of the given class name. Somewhat naive to inner classes. + * + * @param className class name to chew on + * @return the short name of the class + */ + public static String shortNameOf( String className ) { + return className.substring( className.lastIndexOf( '.' ) + 1 ); + } + + /** + * Gives the primitive wrapper class for the given class. If the given class is not + * {@linkplain Class#isPrimitive() primitive}, returns the class itself. + * + * @param <T> generic class type + * @param clazz the class to check + * @return primitive wrapper type if {@code clazz} is primitive, otherwise {@code clazz} + */ + @SuppressWarnings( "unchecked" ) + public static <T> Class<T> wrapperOf( Class<T> clazz ) { + return clazz.isPrimitive() ? (Class<T>) WRAPPERS.get( clazz ) : clazz; + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Columns.java b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Columns.java new file mode 100644 index 0000000000..a012b601f0 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Columns.java @@ -0,0 +1,106 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.internal; + +import java.text.BreakIterator; +import java.util.ArrayList; +import java.util.List; + +import static java.text.BreakIterator.*; + +import static joptsimple.internal.Strings.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +class Columns { + private static final int INDENT_WIDTH = 2; + + private final int optionWidth; + private final int descriptionWidth; + + Columns( int optionWidth, int descriptionWidth ) { + this.optionWidth = optionWidth; + this.descriptionWidth = descriptionWidth; + } + + List<Row> fit( Row row ) { + List<String> options = piecesOf( row.option, optionWidth ); + List<String> descriptions = piecesOf( row.description, descriptionWidth ); + + List<Row> rows = new ArrayList<>(); + for ( int i = 0; i < Math.max( options.size(), descriptions.size() ); ++i ) + rows.add( new Row( itemOrEmpty( options, i ), itemOrEmpty( descriptions, i ) ) ); + + return rows; + } + + private static String itemOrEmpty( List<String> items, int index ) { + return index >= items.size() ? "" : items.get( index ); + } + + private List<String> piecesOf( String raw, int width ) { + List<String> pieces = new ArrayList<>(); + + for ( String each : raw.trim().split( LINE_SEPARATOR ) ) + pieces.addAll( piecesOfEmbeddedLine( each, width ) ); + + return pieces; + } + + private List<String> piecesOfEmbeddedLine( String line, int width ) { + List<String> pieces = new ArrayList<>(); + + BreakIterator words = BreakIterator.getLineInstance(); + words.setText( line ); + + StringBuilder nextPiece = new StringBuilder(); + + int start = words.first(); + for ( int end = words.next(); end != DONE; start = end, end = words.next() ) + nextPiece = processNextWord( line, nextPiece, start, end, width, pieces ); + + if ( nextPiece.length() > 0 ) + pieces.add( nextPiece.toString() ); + + return pieces; + } + + private StringBuilder processNextWord( String source, StringBuilder nextPiece, int start, int end, int width, + List<String> pieces ) { + StringBuilder augmented = nextPiece; + + String word = source.substring( start, end ); + if ( augmented.length() + word.length() > width ) { + pieces.add( augmented.toString().replaceAll( "\\s+$", "" ) ); + augmented = new StringBuilder( repeat( ' ', INDENT_WIDTH ) ).append( word ); + } + else + augmented.append( word ); + + return augmented; + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/internal/ConstructorInvokingValueConverter.java b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/ConstructorInvokingValueConverter.java new file mode 100644 index 0000000000..d3a641b57d --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/ConstructorInvokingValueConverter.java @@ -0,0 +1,56 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.internal; + +import java.lang.reflect.Constructor; + +import joptsimple.ValueConverter; + +import static joptsimple.internal.Reflection.*; + +/** + * @param <V> constraint on the type of values being converted to + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +class ConstructorInvokingValueConverter<V> implements ValueConverter<V> { + private final Constructor<V> ctor; + + ConstructorInvokingValueConverter( Constructor<V> ctor ) { + this.ctor = ctor; + } + + public V convert( String value ) { + return instantiate( ctor, value ); + } + + public Class<V> valueType() { + return ctor.getDeclaringClass(); + } + + public String valuePattern() { + return null; + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Messages.java b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Messages.java new file mode 100644 index 0000000000..5bb71fc727 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Messages.java @@ -0,0 +1,47 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.internal; + +import java.text.MessageFormat; +import java.util.Locale; +import java.util.ResourceBundle; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class Messages { + private Messages() { + throw new UnsupportedOperationException(); + } + + public static String message( Locale locale, String bundleName, Class<?> type, String key, Object... args ) { + ResourceBundle bundle = ResourceBundle.getBundle( bundleName, locale ); + String template = bundle.getString( type.getName() + '.' + key ); + MessageFormat format = new MessageFormat( template ); + format.setLocale( locale ); + return format.format( args ); + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/internal/MethodInvokingValueConverter.java b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/MethodInvokingValueConverter.java new file mode 100644 index 0000000000..503d6778d8 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/MethodInvokingValueConverter.java @@ -0,0 +1,58 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.internal; + +import java.lang.reflect.Method; + +import joptsimple.ValueConverter; + +import static joptsimple.internal.Reflection.*; + +/** + * @param <V> constraint on the type of values being converted to + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +class MethodInvokingValueConverter<V> implements ValueConverter<V> { + private final Method method; + private final Class<V> clazz; + + MethodInvokingValueConverter( Method method, Class<V> clazz ) { + this.method = method; + this.clazz = clazz; + } + + public V convert( String value ) { + return clazz.cast( invoke( method, value ) ); + } + + public Class<V> valueType() { + return clazz; + } + + public String valuePattern() { + return null; + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/internal/OptionNameMap.java b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/OptionNameMap.java new file mode 100644 index 0000000000..1b9e49197b --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/OptionNameMap.java @@ -0,0 +1,47 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.internal; + +import java.util.Map; + +/** + * Map-like interface for storing String-value pairs. + * + * @param <V> type of values stored in the map + */ +public interface OptionNameMap<V> { + boolean contains( String key ); + + V get( String key ); + + void put( String key, V newValue ); + + void putAll( Iterable<String> keys, V newValue ); + + void remove( String key ); + + Map<String, V> toJavaUtilMap(); +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Reflection.java b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Reflection.java new file mode 100644 index 0000000000..5dad882787 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Reflection.java @@ -0,0 +1,142 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.internal; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import static java.lang.reflect.Modifier.*; + +import joptsimple.ValueConverter; + +import static joptsimple.internal.Classes.*; + +/** + * Helper methods for reflection. + * + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public final class Reflection { + private Reflection() { + throw new UnsupportedOperationException(); + } + + /** + * Finds an appropriate value converter for the given class. + * + * @param <V> a constraint on the class object to introspect + * @param clazz class to introspect on + * @return a converter method or constructor + */ + public static <V> ValueConverter<V> findConverter( Class<V> clazz ) { + Class<V> maybeWrapper = wrapperOf( clazz ); + + ValueConverter<V> valueOf = valueOfConverter( maybeWrapper ); + if ( valueOf != null ) + return valueOf; + + ValueConverter<V> constructor = constructorConverter( maybeWrapper ); + if ( constructor != null ) + return constructor; + + throw new IllegalArgumentException( clazz + " is not a value type" ); + } + + private static <V> ValueConverter<V> valueOfConverter( Class<V> clazz ) { + try { + Method valueOf = clazz.getMethod( "valueOf", String.class ); + if ( meetsConverterRequirements( valueOf, clazz ) ) + return new MethodInvokingValueConverter<>( valueOf, clazz ); + + return null; + } catch ( NoSuchMethodException ignored ) { + return null; + } + } + + private static <V> ValueConverter<V> constructorConverter( Class<V> clazz ) { + try { + return new ConstructorInvokingValueConverter<>( clazz.getConstructor( String.class ) ); + } catch ( NoSuchMethodException ignored ) { + return null; + } + } + + /** + * Invokes the given constructor with the given arguments. + * + * @param <T> constraint on the type of the objects yielded by the constructor + * @param constructor constructor to invoke + * @param args arguments to hand to the constructor + * @return the result of invoking the constructor + * @throws ReflectionException in lieu of the gaggle of reflection-related exceptions + */ + public static <T> T instantiate( Constructor<T> constructor, Object... args ) { + try { + return constructor.newInstance( args ); + } catch ( Exception ex ) { + throw reflectionException( ex ); + } + } + + /** + * Invokes the given static method with the given arguments. + * + * @param method method to invoke + * @param args arguments to hand to the method + * @return the result of invoking the method + * @throws ReflectionException in lieu of the gaggle of reflection-related exceptions + */ + public static Object invoke( Method method, Object... args ) { + try { + return method.invoke( null, args ); + } catch ( Exception ex ) { + throw reflectionException( ex ); + } + } + + @SuppressWarnings( "unchecked" ) + public static <V> V convertWith( ValueConverter<V> converter, String raw ) { + return converter == null ? (V) raw : converter.convert( raw ); + } + + private static boolean meetsConverterRequirements( Method method, Class<?> expectedReturnType ) { + int modifiers = method.getModifiers(); + return isPublic( modifiers ) && isStatic( modifiers ) && expectedReturnType.equals( method.getReturnType() ); + } + + private static RuntimeException reflectionException( Exception ex ) { + if ( ex instanceof IllegalArgumentException ) + return new ReflectionException( ex ); + if ( ex instanceof InvocationTargetException ) + return new ReflectionException( ex.getCause() ); + if ( ex instanceof RuntimeException ) + return (RuntimeException) ex; + + return new ReflectionException( ex ); + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/internal/ReflectionException.java b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/ReflectionException.java new file mode 100644 index 0000000000..17cd4d6330 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/ReflectionException.java @@ -0,0 +1,39 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.internal; + +/** + * This unchecked exception wraps reflection-oriented exceptions. + * + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class ReflectionException extends RuntimeException { + private static final long serialVersionUID = -2L; + + ReflectionException( Throwable cause ) { + super( cause ); + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Row.java b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Row.java new file mode 100644 index 0000000000..13d8e34905 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Row.java @@ -0,0 +1,55 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.internal; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +class Row { + final String option; + final String description; + + Row( String option, String description ) { + this.option = option; + this.description = description; + } + + @Override + public boolean equals( Object that ) { + if ( that == this ) + return true; + if ( that == null || !getClass().equals( that.getClass() ) ) + return false; + + Row other = (Row) that; + return option.equals( other.option ) && description.equals( other.description ); + } + + @Override + public int hashCode() { + return option.hashCode() ^ description.hashCode(); + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Rows.java b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Rows.java new file mode 100644 index 0000000000..c2cae82ce4 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Rows.java @@ -0,0 +1,103 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.internal; + +import java.util.ArrayList; +import java.util.List; + +import static java.lang.Math.*; + +import static joptsimple.internal.Strings.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class Rows { + private final int overallWidth; + private final int columnSeparatorWidth; + private final List<Row> rows = new ArrayList<>(); + + private int widthOfWidestOption; + private int widthOfWidestDescription; + + public Rows( int overallWidth, int columnSeparatorWidth ) { + this.overallWidth = overallWidth; + this.columnSeparatorWidth = columnSeparatorWidth; + } + + public void add( String option, String description ) { + add( new Row( option, description ) ); + } + + private void add( Row row ) { + rows.add( row ); + widthOfWidestOption = max( widthOfWidestOption, row.option.length() ); + widthOfWidestDescription = max( widthOfWidestDescription, row.description.length() ); + } + + public void reset() { + rows.clear(); + widthOfWidestOption = 0; + widthOfWidestDescription = 0; + } + + public void fitToWidth() { + Columns columns = new Columns( optionWidth(), descriptionWidth() ); + + List<Row> fitted = new ArrayList<>(); + for ( Row each : rows ) + fitted.addAll( columns.fit( each ) ); + + reset(); + + for ( Row each : fitted ) + add( each ); + } + + public String render() { + StringBuilder buffer = new StringBuilder(); + + for ( Row each : rows ) { + pad( buffer, each.option, optionWidth() ).append( repeat( ' ', columnSeparatorWidth ) ); + pad( buffer, each.description, descriptionWidth() ).append( LINE_SEPARATOR ); + } + + return buffer.toString(); + } + + private int optionWidth() { + return min( ( overallWidth - columnSeparatorWidth ) / 2, widthOfWidestOption ); + } + + private int descriptionWidth() { + return min( overallWidth - optionWidth() - columnSeparatorWidth, widthOfWidestDescription ); + } + + private StringBuilder pad( StringBuilder buffer, String s, int length ) { + buffer.append( s ).append( repeat( ' ', length - s.length() ) ); + return buffer; + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/internal/SimpleOptionNameMap.java b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/SimpleOptionNameMap.java new file mode 100644 index 0000000000..69ad6b5c4c --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/SimpleOptionNameMap.java @@ -0,0 +1,67 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.internal; + +import java.util.HashMap; +import java.util.Map; + +/** + * <p>An {@code OptionNameMap} which wraps and behaves like {@code HashMap}.</p> + */ +public class SimpleOptionNameMap<V> implements OptionNameMap<V> { + private final Map<String, V> map = new HashMap<>(); + + @Override + public boolean contains( String key ) { + return map.containsKey( key ); + } + + @Override + public V get( String key ) { + return map.get( key ); + } + + @Override + public void put( String key, V newValue ) { + map.put( key, newValue ); + } + + @Override + public void putAll( Iterable<String> keys, V newValue ) { + for ( String each : keys ) + map.put( each, newValue ); + } + + @Override + public void remove( String key ) { + map.remove( key ); + } + + @Override + public Map<String, V> toJavaUtilMap() { + return new HashMap<>( map ); + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Strings.java b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Strings.java new file mode 100644 index 0000000000..50ea3e49ea --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/internal/Strings.java @@ -0,0 +1,115 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.internal; + +import java.util.Iterator; + +import static java.lang.System.*; +import static java.util.Arrays.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public final class Strings { + public static final String EMPTY = ""; + public static final String LINE_SEPARATOR = getProperty( "line.separator" ); + + private Strings() { + throw new UnsupportedOperationException(); + } + + /** + * Gives a string consisting of the given character repeated the given number of times. + * + * @param ch the character to repeat + * @param count how many times to repeat the character + * @return the resultant string + */ + public static String repeat( char ch, int count ) { + StringBuilder buffer = new StringBuilder(); + + for ( int i = 0; i < count; ++i ) + buffer.append( ch ); + + return buffer.toString(); + } + + /** + * Tells whether the given string is either {@code} or consists solely of whitespace characters. + * + * @param target string to check + * @return {@code true} if the target string is null or empty + */ + public static boolean isNullOrEmpty( String target ) { + return target == null || target.isEmpty(); + } + + + /** + * Gives a string consisting of a given string prepended and appended with surrounding characters. + * + * @param target a string + * @param begin character to prepend + * @param end character to append + * @return the surrounded string + */ + public static String surround( String target, char begin, char end ) { + return begin + target + end; + } + + /** + * Gives a string consisting of the elements of a given array of strings, each separated by a given separator + * string. + * + * @param pieces the strings to join + * @param separator the separator + * @return the joined string + */ + public static String join( String[] pieces, String separator ) { + return join( asList( pieces ), separator ); + } + + /** + * Gives a string consisting of the string representations of the elements of a given array of objects, + * each separated by a given separator string. + * + * @param pieces the elements whose string representations are to be joined + * @param separator the separator + * @return the joined string + */ + public static String join( Iterable<String> pieces, String separator ) { + StringBuilder buffer = new StringBuilder(); + + for ( Iterator<String> iter = pieces.iterator(); iter.hasNext(); ) { + buffer.append( iter.next() ); + + if ( iter.hasNext() ) + buffer.append( separator ); + } + + return buffer.toString(); + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/util/DateConverter.java b/third_party/java/jopt-simple/src/main/java/joptsimple/util/DateConverter.java new file mode 100644 index 0000000000..c3182ae2fd --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/util/DateConverter.java @@ -0,0 +1,114 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.util; + +import java.text.DateFormat; +import java.text.ParsePosition; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +import joptsimple.ValueConversionException; +import joptsimple.ValueConverter; +import joptsimple.internal.Messages; + +/** + * Converts values to {@link Date}s using a {@link DateFormat} object. + * + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class DateConverter implements ValueConverter<Date> { + private final DateFormat formatter; + + /** + * Creates a converter that uses the given date formatter/parser. + * + * @param formatter the formatter/parser to use + * @throws NullPointerException if {@code formatter} is {@code null} + */ + public DateConverter( DateFormat formatter ) { + if ( formatter == null ) + throw new NullPointerException( "illegal null formatter" ); + + this.formatter = formatter; + } + + /** + * Creates a converter that uses a {@link SimpleDateFormat} with the given date/time pattern. The date formatter + * created is not {@link SimpleDateFormat#setLenient(boolean) lenient}. + * + * @param pattern expected date/time pattern + * @return the new converter + * @throws NullPointerException if {@code pattern} is {@code null} + * @throws IllegalArgumentException if {@code pattern} is invalid + */ + public static DateConverter datePattern( String pattern ) { + SimpleDateFormat formatter = new SimpleDateFormat( pattern ); + formatter.setLenient( false ); + + return new DateConverter( formatter ); + } + + public Date convert( String value ) { + ParsePosition position = new ParsePosition( 0 ); + + Date date = formatter.parse( value, position ); + if ( position.getIndex() != value.length() ) + throw new ValueConversionException( message( value ) ); + + return date; + } + + public Class<Date> valueType() { + return Date.class; + } + + public String valuePattern() { + return formatter instanceof SimpleDateFormat + ? ( (SimpleDateFormat) formatter ).toPattern() + : ""; + } + + private String message( String value ) { + String key; + Object[] arguments; + + if ( formatter instanceof SimpleDateFormat ) { + key = "with.pattern.message"; + arguments = new Object[] { value, ( (SimpleDateFormat) formatter ).toPattern() }; + } else { + key = "without.pattern.message"; + arguments = new Object[] { value }; + } + + return Messages.message( + Locale.getDefault(), + "joptsimple.ExceptionMessages", + DateConverter.class, + key, + arguments ); + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/util/EnumConverter.java b/third_party/java/jopt-simple/src/main/java/joptsimple/util/EnumConverter.java new file mode 100644 index 0000000000..c75b86607f --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/util/EnumConverter.java @@ -0,0 +1,104 @@ +/* + The MIT License + + Copyright (c) 2004-2014 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.util; + +import java.text.MessageFormat; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.ResourceBundle; + +import joptsimple.ValueConversionException; +import joptsimple.ValueConverter; + +/** + * Converts values to {@link java.lang.Enum}s. + * + * @author <a href="mailto:christian.ohr@gmail.com">Christian Ohr</a> + */ +public abstract class EnumConverter<E extends Enum<E>> implements ValueConverter<E> { + private final Class<E> clazz; + + private String delimiters = "[,]"; + + /** + * This constructor must be called by subclasses, providing the enum class as the parameter. + * + * @param clazz enum class + */ + protected EnumConverter( Class<E> clazz ) { + this.clazz = clazz; + } + + @Override + public E convert( String value ) { + for ( E each : valueType().getEnumConstants() ) { + if ( each.name().equalsIgnoreCase( value ) ) { + return each; + } + } + + throw new ValueConversionException( message( value ) ); + } + + @Override + public Class<E> valueType() { + return clazz; + } + + /** + * Sets the delimiters for the message string. Must be a 3-letter string, + * where the first character is the prefix, the second character is the + * delimiter between the values, and the 3rd character is the suffix. + * + * @param delimiters delimiters for message string. Default is [,] + */ + public void setDelimiters( String delimiters ) { + this.delimiters = delimiters; + } + + @Override + public String valuePattern() { + EnumSet<E> values = EnumSet.allOf( valueType() ); + + StringBuilder builder = new StringBuilder(); + builder.append( delimiters.charAt(0) ); + for ( Iterator<E> i = values.iterator(); i.hasNext(); ) { + builder.append( i.next().toString() ); + if ( i.hasNext() ) + builder.append( delimiters.charAt( 1 ) ); + } + builder.append( delimiters.charAt( 2 ) ); + + return builder.toString(); + } + + private String message( String value ) { + ResourceBundle bundle = ResourceBundle.getBundle( "joptsimple.ExceptionMessages" ); + Object[] arguments = new Object[] { value, valuePattern() }; + String template = bundle.getString( EnumConverter.class.getName() + ".message" ); + return new MessageFormat( template ).format( arguments ); + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/util/InetAddressConverter.java b/third_party/java/jopt-simple/src/main/java/joptsimple/util/InetAddressConverter.java new file mode 100644 index 0000000000..2f116f810d --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/util/InetAddressConverter.java @@ -0,0 +1,67 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.util; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Locale; + +import joptsimple.ValueConversionException; +import joptsimple.ValueConverter; +import joptsimple.internal.Messages; + +/** + * Converts values to {@link java.net.InetAddress} using {@link InetAddress#getByName(String) getByName}. + * + * @author <a href="mailto:r@ymund.de">Raymund F\u00FCl\u00F6p</a> + */ +public class InetAddressConverter implements ValueConverter<InetAddress> { + public InetAddress convert( String value ) { + try { + return InetAddress.getByName( value ); + } + catch ( UnknownHostException e ) { + throw new ValueConversionException( message( value ) ); + } + } + + public Class<InetAddress> valueType() { + return InetAddress.class; + } + + public String valuePattern() { + return null; + } + + private String message( String value ) { + return Messages.message( + Locale.getDefault(), + "joptsimple.ExceptionMessages", + InetAddressConverter.class, + "message", + value ); + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/util/KeyValuePair.java b/third_party/java/jopt-simple/src/main/java/joptsimple/util/KeyValuePair.java new file mode 100644 index 0000000000..bdc2424190 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/util/KeyValuePair.java @@ -0,0 +1,83 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.util; + +import static joptsimple.internal.Strings.*; + +/** + * <p>A simple string key/string value pair.</p> + * + * <p>This is useful as an argument type for options whose values take on the form {@code key=value}, such as JVM + * command line system properties.</p> + * + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public final class KeyValuePair { + public final String key; + public final String value; + + private KeyValuePair( String key, String value ) { + this.key = key; + this.value = value; + } + + /** + * Parses a string assumed to be of the form {@code key=value} into its parts. + * + * @param asString key-value string + * @return a key-value pair + * @throws NullPointerException if {@code stringRepresentation} is {@code null} + */ + public static KeyValuePair valueOf( String asString ) { + int equalsIndex = asString.indexOf( '=' ); + if ( equalsIndex == -1 ) + return new KeyValuePair( asString, EMPTY ); + + String aKey = asString.substring( 0, equalsIndex ); + String aValue = equalsIndex == asString.length() - 1 ? EMPTY : asString.substring( equalsIndex + 1 ); + + return new KeyValuePair( aKey, aValue ); + } + + @Override + public boolean equals( Object that ) { + if ( !( that instanceof KeyValuePair ) ) + return false; + + KeyValuePair other = (KeyValuePair) that; + return key.equals( other.key ) && value.equals( other.value ); + } + + @Override + public int hashCode() { + return key.hashCode() ^ value.hashCode(); + } + + @Override + public String toString() { + return key + '=' + value; + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/util/PathConverter.java b/third_party/java/jopt-simple/src/main/java/joptsimple/util/PathConverter.java new file mode 100644 index 0000000000..295bc00362 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/util/PathConverter.java @@ -0,0 +1,51 @@ +package joptsimple.util; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.text.MessageFormat; +import java.util.ResourceBundle; + +import joptsimple.ValueConversionException; +import joptsimple.ValueConverter; + +/** + * Converts command line options to {@link Path} objects and checks the status of the underlying file. + */ +public class PathConverter implements ValueConverter<Path> { + private final PathProperties[] pathProperties; + + public PathConverter( PathProperties... pathProperties ) { + this.pathProperties = pathProperties; + } + + @Override + public Path convert( String value ) { + Path path = Paths.get(value); + + if ( pathProperties != null ) { + for ( PathProperties each : pathProperties ) { + if ( !each.accept( path ) ) + throw new ValueConversionException( message( each.getMessageKey(), path.toString() ) ); + } + } + + return path; + } + + @Override + public Class<Path> valueType() { + return Path.class; + } + + @Override + public String valuePattern() { + return null; + } + + private String message( String errorKey, String value ) { + ResourceBundle bundle = ResourceBundle.getBundle( "joptsimple.ExceptionMessages" ); + Object[] arguments = new Object[] { value, valuePattern() }; + String template = bundle.getString( PathConverter.class.getName() + "." + errorKey + ".message" ); + return new MessageFormat( template ).format( arguments ); + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/util/PathProperties.java b/third_party/java/jopt-simple/src/main/java/joptsimple/util/PathProperties.java new file mode 100644 index 0000000000..a7fb045025 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/util/PathProperties.java @@ -0,0 +1,60 @@ +package joptsimple.util; + +import java.nio.file.Files; +import java.nio.file.Path; + +/** + * Enum for checking common conditions of files and directories. + * + * @see joptsimple.util.PathConverter + */ +public enum PathProperties { + FILE_EXISTING( "file.existing" ) { + @Override + boolean accept( Path path ) { + return Files.isRegularFile( path ); + } + }, + DIRECTORY_EXISTING( "directory.existing" ) { + @Override + boolean accept( Path path ) { + return Files.isDirectory( path ); + } + }, + NOT_EXISTING( "file.not.existing" ) { + @Override + boolean accept( Path path ) { + return Files.notExists( path ); + } + }, + FILE_OVERWRITABLE( "file.overwritable" ) { + @Override + boolean accept( Path path ) { + return FILE_EXISTING.accept( path ) && WRITABLE.accept( path ); + } + }, + READABLE( "file.readable" ) { + @Override + boolean accept( Path path ) { + return Files.isReadable( path ); + } + }, + WRITABLE( "file.writable" ) { + @Override + boolean accept( Path path ) { + return Files.isWritable( path ); + } + }; + + private final String messageKey; + + private PathProperties( String messageKey ) { + this.messageKey = messageKey; + } + + abstract boolean accept( Path path ); + + String getMessageKey() { + return messageKey; + } +} diff --git a/third_party/java/jopt-simple/src/main/java/joptsimple/util/RegexMatcher.java b/third_party/java/jopt-simple/src/main/java/joptsimple/util/RegexMatcher.java new file mode 100644 index 0000000000..aca788c7ec --- /dev/null +++ b/third_party/java/jopt-simple/src/main/java/joptsimple/util/RegexMatcher.java @@ -0,0 +1,95 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.util; + +import java.util.Locale; +import java.util.regex.Pattern; + +import static java.util.regex.Pattern.*; +import static joptsimple.internal.Messages.message; + +import joptsimple.ValueConversionException; +import joptsimple.ValueConverter; + +/** + * Ensures that values entirely match a regular expression. + * + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class RegexMatcher implements ValueConverter<String> { + private final Pattern pattern; + + /** + * Creates a matcher that uses the given regular expression, modified by the given flags. + * + * @param pattern the regular expression pattern + * @param flags modifying regex flags + * @throws IllegalArgumentException if bit values other than those corresponding to the defined match flags are + * set in {@code flags} + * @throws java.util.regex.PatternSyntaxException if the expression's syntax is invalid + */ + public RegexMatcher( String pattern, int flags ) { + this.pattern = compile( pattern, flags ); + } + + /** + * Gives a matcher that uses the given regular expression. + * + * @param pattern the regular expression pattern + * @return the new converter + * @throws java.util.regex.PatternSyntaxException if the expression's syntax is invalid + */ + public static ValueConverter<String> regex( String pattern ) { + return new RegexMatcher( pattern, 0 ); + } + + public String convert( String value ) { + if ( !pattern.matcher( value ).matches() ) { + raiseValueConversionFailure( value ); + } + + return value; + } + + public Class<String> valueType() { + return String.class; + } + + public String valuePattern() { + return pattern.pattern(); + } + + private void raiseValueConversionFailure( String value ) { + String message = message( + Locale.getDefault(), + "joptsimple.ExceptionMessages", + RegexMatcher.class, + "message", + value, + pattern.pattern() ); + throw new ValueConversionException( message ); + } +} diff --git a/third_party/java/jopt-simple/src/main/resources/joptsimple/ExceptionMessages.properties b/third_party/java/jopt-simple/src/main/resources/joptsimple/ExceptionMessages.properties new file mode 100644 index 0000000000..e5ce44d8c3 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/resources/joptsimple/ExceptionMessages.properties @@ -0,0 +1,19 @@ +joptsimple.IllegalOptionSpecificationException.message = {0} is not a legal option character +joptsimple.MissingRequiredOptionsException.message = Missing required option(s) {0} +joptsimple.MultipleArgumentsForOptionException.message = Found multiple arguments for option {0}, but you asked for only one +joptsimple.OptionArgumentConversionException.message = Cannot parse argument ''{0}'' of option {1} +joptsimple.OptionMissingRequiredArgumentException.message = Option {0} requires an argument +joptsimple.UnavailableOptionException.message = Option(s) {0} are unavailable given other options on the command line +joptsimple.UnconfiguredOptionException.message = Option(s) {0} not configured on this parser +joptsimple.UnrecognizedOptionException.message = {0} is not a recognized option +joptsimple.util.DateConverter.without.pattern.message = Value [{0}] does not match date/time pattern +joptsimple.util.DateConverter.with.pattern.message = Value [{0}] does not match date/time pattern [{1}] +joptsimple.util.RegexMatcher.message = Value [{0}] did not match regex [{1}] +joptsimple.util.EnumConverter.message = Value [{0}] is not one of [{1}] +joptsimple.util.PathConverter.file.existing.message = File [{0}] does not exist +joptsimple.util.PathConverter.directory.existing.message = Directory [{0}] does not exist +joptsimple.util.PathConverter.file.not.existing.message = File [{0}] does already exist +joptsimple.util.PathConverter.file.overwritable.message = File [{0}] is not overwritable +joptsimple.util.PathConverter.file.readable.message = File [{0}] is not readable +joptsimple.util.PathConverter.file.writable.message = File [{0}] is not writable +joptsimple.util.InetAddressConverter.message = Cannot convert value [{0}] into an InetAddress
\ No newline at end of file diff --git a/third_party/java/jopt-simple/src/main/resources/joptsimple/HelpFormatterMessages.properties b/third_party/java/jopt-simple/src/main/resources/joptsimple/HelpFormatterMessages.properties new file mode 100644 index 0000000000..d0faea73e4 --- /dev/null +++ b/third_party/java/jopt-simple/src/main/resources/joptsimple/HelpFormatterMessages.properties @@ -0,0 +1,11 @@ +joptsimple.BuiltinHelpFormatter.no.options.specified = No options specified +joptsimple.BuiltinHelpFormatter.non.option.arguments.header = Non-option arguments: +joptsimple.BuiltinHelpFormatter.option.header.with.required.indicator = Option (* = required) +joptsimple.BuiltinHelpFormatter.option.divider.with.required.indicator = --------------------- +joptsimple.BuiltinHelpFormatter.option.header = Option +joptsimple.BuiltinHelpFormatter.option.divider = ------ +joptsimple.BuiltinHelpFormatter.description.header = Description +joptsimple.BuiltinHelpFormatter.description.divider = ----------- +joptsimple.BuiltinHelpFormatter.default.value.header = default: +joptsimple.AlternativeLongOptionSpec.description = Alternative form of long options +joptsimple.AlternativeLongOptionSpec.arg.description = opt=value diff --git a/third_party/java/jopt-simple/src/site/apt/acknowledgments.apt b/third_party/java/jopt-simple/src/site/apt/acknowledgments.apt new file mode 100644 index 0000000000..ec35ed7e19 --- /dev/null +++ b/third_party/java/jopt-simple/src/site/apt/acknowledgments.apt @@ -0,0 +1,90 @@ + --------------- + Acknowledgments + --------------- + + Thanks to the following people who have offered constructive feedback, support, contribution, + and/or praise for JOpt Simple: + + * Paul Armstrong + + * Guillaume Aubert + + * David Beckingsale + + * Jochen Bedersdorfer + + * Louis Bergelson + + * Ryan Breidenbach + + * Erik Broes + + * Carlos Cadete + + * Laurent Caillette + + * Matthew Daniel + + * Hans Dockter + + * Kevin C. Dorff + + * Adam Fisk + + * Raymund F\u00FCl\u00F6p + + * Dave Jarvis + + * Paul King + + * El Kodus + + * Alexander Kriegisch + + * Zachary Kurmas + + * Henning Luebbers + + * Derek Mahar + + * Bruno Mascret + + * Antoine Neveux + + * Christian Ohr + + * Michael Osipov + + * Brian Oxley (binkley) + + * Andrew Parker + + * Julien Ponge + + * Rob Reed + + * Mark Reinhold + + * Alex Renger + + * Andrew Robinson + + * Jonathan Shook + + * Jason Smith + + * Emils Solmanis + + * Leo Uzcategui + + * Alan van Dam + + * Douglas Wegscheid + + * Chris K Wensel + + * Ashley Williams + + * Daniel Yokomizo + + [] diff --git a/third_party/java/jopt-simple/src/site/apt/changes.apt b/third_party/java/jopt-simple/src/site/apt/changes.apt new file mode 100644 index 0000000000..2bc0d7d9c6 --- /dev/null +++ b/third_party/java/jopt-simple/src/site/apt/changes.apt @@ -0,0 +1,385 @@ + ---------- + Change Log + ---------- + +Changes in version 5.0.3 + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/96} gh-96}} so that + options that take an argument but don't change the argument type from + <<<String>>> still show a <<<String>>> type indicator in the default + option help. + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/104} gh-104}} so + that <<<EnumConverter>>> performs case-insensitive matching against arguments + of options. Thanks to Martin Paljak for this. + +Changes in version 5.0.2 + + * Made some package-private abstract classes become public classes + with package-private constructors. This makes it possible to call some methods + from Kotlin that were previously inaccessible. Thanks to Mirko Friedenhagen + for this. + +Changes in version 5.0.1 + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/92} gh-92}} so that + in the event that <<<printHelpOn()>>> is called more than once, the output + is not duplicated. + +Changes in version 5.0 + + * Abandoning JDKs prior to 7. All source is Java 7-compatible, and bytecode is compiled to 1.7 + version. + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/51} gh-51}} by adding + <<<OptionSpecBuilder.availableIf()>>> and <<<OptionSpecBuilder.availableUnless()>>>. Thanks + to Christian Ohr for this. + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/70} gh-70}} by adding + <<<EnumConverter>>> and <<<PathConverter>>>. Thanks to Christian Ohr for this. + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/88} gh-88}} by adding + an <<<OptionParser>>> constructor to allow suppression of option abbreviations. + Thanks to Louis Bergelson for this. + +Changes in version 4.10 + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/85} gh-85}} + by correcting the description column width consumption of the built-in + help formatter. + +Changes in version 4.9 + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/79} gh-79}} + by correcting the behavior of <<<OptionException.multipleOptionString>>> + when handling options with synonyms. + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/72} gh-72}} + by externalizing some of the literal strings in <<<BuiltinHelpFormatter>>> + into resource bundles. + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/76} gh-76}} + by modifying the behavior of <<<OptionalArgumentOptionSpec>>> so that if + the argument following the option does not "look like" an option but can + be converted to the option argument's type, treat the argument as the argument + of the option. + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/68} gh-68}} + by modifying <<<BuiltinHelpFormatter>>> to be more extensible and documenting + the behavior of the newly accessible methods. + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/73} gh-73}} + by correcting the behavior of <<<OptionSet.specs()>>> to remove all instances + of the non-option argument spec. + +Changes in version 4.8 + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/65} gh-65}} + by modifying the build file to create a JAR with OSGi metadata. + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/63} gh-63}} + by externalizing exception messages into resource bundles. + Currently, we ship only with messages for locale "en_US". + Translations for other locales are more than welcome. + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/58} gh-58}} by + rewriting exception messaging to clarify synonymous options. + Synonyms are be separated by slashes (/); lists of distinct options will + be separated by commas (,) in square brackets ([]). + +Changes in version 4.7 + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/57} gh-57}} by admitting + the underscore as a legal option character. + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/53} gh-53}} by correcting + <<<OptionSet.hasOptions()>>> to answer correctly for no switches. + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/56} gh-56}} by correcting + the default help formatting not to use a <<<Set>>> for rows of output, + but <<<List>>>. + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/59} gh-59}} by relaxing + the return type of <<<ValueConverter.valueType()>>>. + +Changes in version 4.6 + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/31} gh-31}} by offering + <<<OptionSpecBuilder.requiredUnless()>>>. Thanks to Christian Ohr for this. + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/38} gh-38}} by offering + <<<OptionParser.recognizedOptions()>>>. Thanks to Antoine Neveux for this. + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/35} gh-35}} by offering + <<<OptionSet.asMap()>>>. Thanks to Brian Oxley for this. + +Changes in version 4.5 + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/17} gh-17}} by offering + <<<OptionParser.nonOptions()>>> and <<<NonOptionArgumentSpec>>>. + + * Resolved {{{https://github.com/pholser/jopt-simple/pull/27} gh-27}} by offering + <<<OptionParser.allowsUnrecognizedOptions()>>>. Thanks to Erik Broes for this. + +Changes in version 4.4 + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/16} gh-16}} by offering + <<<BuiltinHelpFormatter>>> that allows configuration of overall row width and + column separator width. Thanks to Ryan Breidenbach for contributing code to this. + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/12} gh-12}} by offering + <<<OptionSpecBuilder.requiredIf()>>>. + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/22} gh-22}}. Thanks to + El Kodus for this. + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/19} gh-19}}. Thanks to + El Kodus for this. + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/14} gh-14}} by offering + <<<AbstractOptionSpec.forHelp()>>>. + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/13} gh-13}} by offering + <<<ArgumentAcceptingOptionSpec.withValuesSeparatedBy(String)>>>. + + * Added <<<InetAddressValueConverter>>>. Thanks to Raymund F\u00FCl\u00F6p for this. + +Changes in version 4.3 + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/9} gh-9}} by offering + <<<OptionSet.specs()>>>, which gives a list of the specs corresponding to the + options detected on a parse, in the order in which the options occurred on the + command line. + +Changes in version 4.2 + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/8} gh-8}} by offering + <<<ArgumentAcceptingOptionSpec.defaultsTo(V[])>>> in addition to + <<<ArgumentAcceptingOptionSpec.defaultsTo(V, V...)>>>. + + * Removing some internal unused classes and methods. + +Changes in version 4.1 + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/7} gh-7}} by allowing short option + clusters to contain options which can accept arguments. When such an option is encountered, + the remaining characters in the cluster are treated as the argument to the option. Thanks to + Alan van Dam for this. + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/6} gh-6}} with general improvements + to the project's site. Thanks to Michael Osipov for this. + +Changes in version 4.0 + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/4} gh-4}} by adding method + <<<OptionParser.formatHelpWith(HelpFormatter)>>> to allow programmers to influence what + help is printed with <<<OptionParser.printHelpOn()>>>. A <<<HelpFormatter>>> is handed a + map, keyed by option text, whose values are <<<OptionDescriptor>>>s that describe the + options the parser has been configured with. + + * Added method <<<OptionSet.hasOptions()>>>. Thanks to Michael Osipov for this. + + * Resolved {{{https://github.com/pholser/jopt-simple/pull/3} gh-3}} by using + <<<SimpleDateFormat.toPattern()>>> rather than <<<SimpleDateFormat.toLocalizedPattern()>>> + in <<<DateConverter>>>. Thanks to Michael Osipov for this. + + * Resolved {{{https://github.com/pholser/jopt-simple/issues/5} gh-5}} by allowing primitive + <<<Class>>> objects whose wrapper types are considered "value types" for purposes of + <<<ArgumentAcceptingOptionSpec.ofType()>>> in place of the wrapper classes. Thanks to + Daniel Yokomizo for suggesting this. + +Changes in version 3.3 + + * Resolved {{{https://github.com/pholser/jopt-simple/pull/1} gh-1}} by adding method + <<<required()>>> to class <<<ArgumentAcceptingOptionSpec>>>, to allow callers to indicate + that a given option must be present on the command line. Thanks to Emils Solmanis for + adding this. + +Changes in version 3.2 + + * Added method <<<defaultsTo()>>> to class <<<ArgumentAcceptingOptionSpec>>>, to allow + callers to specify default values for arguments of options. These influence the return + values of <<<OptionSpec.value(s)()>>> and <<<OptionSet.value(s)Of()>>>. Default values + also show up in the help screen entries for their options. This serves to resolve + {{{https://sourceforge.net/tracker/?func=detail&aid=2484524&group_id=125731&atid=703508} feature + request 2484524}}. + + * Fixed a problem whereby the empty string, a string consisting solely of whitespace, or a + string with embedded whitespace weren't being properly recognized as arguments of options + when they should have. + + * Resolved {{{https://sourceforge.net/tracker/?func=detail&aid=2793762&group_id=125731&atid=703508} feature + request 2793762}}, having to do with improving the behavior of embedded newlines in option + descriptions in help screens. + +Changes in version 3.1 + + * Added method <<<withValuesConvertedBy()>>> to class <<<ArgumentAcceptingOptionSpec>>>, + to allow callers to specify converters or validators that transform arguments of + options into instances of specific Java types. This is useful for types which do not + meet the requirements of <<<ofType()>>>. + + * Added classes <<<DateConverter>>> and <<<RegexMatcher>>> as examples of useful + argument converters. + +Changes in version 3.0.1 + + * Dependency on {{{http://ant.apache.org} Ant}} more appropriately test-scoped in the + {{{http://maven.apache.org} Maven}} POM. That way, if you use JOpt Simple with Maven, + you don't download Ant unnecessarily. + +Changes in version 3.0 + + * Version 3.0 supports Java 5 and greater only. If you need to use JOpt Simple in a + pre-Java-5 environment, use the latest 2.x release. + + * Where appropriate, existing API calls have been updated to use Java generics. + + * Extracted and surfaced interface <<<OptionSpec>>>. <<<OptionSpec>>>s returned by + the fluent interface methods can be used to retrieve arguments of the options they + represent in a type-safe manner. + + * Removed all previously deprecated methods. + + * Added methods to <<<OptionSet>>> to allow detection of options and retrieval of + option arguments using instances of <<<OptionSpec>>>. + + * Converted tests to JUnit 4. + + * Switched to MIT License. + + * Relaxing some <<<List>>> parameter types and return types of methods to + <<<Collection>>>. + + * <<<OptionArgumentConversionException>>> no longer drops the original cause on the + floor; hence <<<OptionException>>> can now be created with a cause. + + * {{{http://maven.apache.org} Maven}}-ized the project web site. + + * Overhauled the examples page. + +Changes in version 2.4.1 + + * Fixed {{{https://sourceforge.net/tracker/index.php?func=detail&aid=2018262&group_id=125731&atid=703505} bug 2018262}}. + +Changes in version 2.4 + + * Added the <<<acceptsAll()>>> method to class <<<OptionParser>>>. Options passed to + a given invocation of this method are treated as synonymous, so that each gives the + same answer when given as the argument to the methods <<<has()>>>, <<<valuesOf()>>>, + etc. on <<<OptionSet>>>. + + * Surfaced the class <<<KeyValuePair>>>. This class can be very handy as a value + type for arguments whose values take on the form <<<key=value>>>, such as the <<<-D>>> + arguments to JVMs. + + * Fixed {{{https://sourceforge.net/tracker/index.php?func=detail&aid=1932577&group_id=125731&atid=703505} bug 1932577}}. + + * Added method <<<withValuesSeparatedBy()>>> to class <<<ArgumentAcceptingOptionSpec>>>, + to allow callers to specify multiple values for an option as a single argument with + values separated by a given character. + + * Method <<<ofType()>>> on class <<<ArgumentAcceptingOptionSpec>>> now returns self + rather than <<<void>>>. + + * Deprecated another "get for get's sake": <<<OptionParser.setPosixlyCorrect()>>> + It is replaced with a less Java-beany-looking method. + + * Cleaned up the help screens produced by <<<OptionParser.printHelpOn()>>> so they are + rendered as two 40-character columns, with long space-broken values split across lines + as needed. + + * Fixed {{{https://sourceforge.net/tracker/index.php?func=detail&aid=1956418&group_id=125731&atid=703505} bug 1956418}}. + +Changes in version 2.3.6 + + * No changes to code; just getting {{{http://maven.apache.org} Maven}} to do releases + with its plugins. + +Changes in version 2.3.3 + + * Deprecated method <<<OptionSet.wasDetected()>>> in favor of <<<OptionSet.has()>>> -- + the new name seems to read better. + + * <<<OptionException>>>s now override <<<getMessage()>>> sensibly, so that if a caller + wants to handle the exception by catching it and displaying a message from the + exception, she can do so and get satisfactory results. + + * {{{http://maven.apache.org} Maven}}-ized project's build. + + * Minor internal changes. + +Changes in version 2.3.2 + + * Minor internal changes. + +Changes in version 2.3.1 + + * Fixed a bug with POSIX-ly correct parsers. It was previously thought that POSIX-ly + correct parsers should signal end of options when they detect an argument that does + not lexically look like an option and could not be an argument of a previous option, + required or optional. Such parsers now signal end of options when they detect an + argument that does not lexically look like an option, and is not an argument of a + previous option with a required argument. If you want such an argument to be treated + as the argument of a preceding option whose argument is optional, you can still get + this behavior by appending the argument to the option, either with abutting syntax + (<<<-d/tmp>>>) or key-value syntax (<<<-d=/tmp>>>). + +Changes in version 2.3 + + * No feature changes in this release; but this release can now be used with JDK 1.3. + Previous releases could be used only with JDK 1.4 or newer. + +Changes in version 2.2 + + * Removed all previously deprecated methods. + + * Re-clarified the contract of the one-arg <<<String>>> constructor of + <<<OptionParser>>>: the constructor now raises <<<NullPointerException>>> if its + argument is <<<null>>>. This is the convention for Java library methods which receive + illegal <<<null>>> parameters. + +Changes in version 2.1 + + * Introduced a facility for <<<OptionParser>>>s to print a help screen, which + describes the options they accept. + + * Added the ability to provide descriptions of options and their arguments when + configuring an <<<OptionParser>>>. These descriptions are printed in the + aforementioned help screens. + + * Clarified the contract of the one-arg <<<String>>> constructor of <<<OptionParser>>>: + the constructor raises <<<IllegalArgumentException>>> if its argument is <<<null>>>. + + * Deprecated <<<OptionParser.noArg()>>>, <<<OptionParser.requiredArg()>>>, and + <<<OptionParser.optionalArg()>>>. + + * Deprecated some "gets for gets' sake": <<<OptionException.getOption()>>>, + <<<OptionSet.getNonOptionArguments()>>>. They are replaced with less + Java-beany-looking methods. + +Changes in version 2.0 + + * Introduced a "fluent interface" API for specifying options for an <<<OptionParser>>> + to recognize. The old methods for option specification still work--you need not + convert to the new methods. + + * Added the ability to specify that option arguments should be converted to specific + types. You can do this either with the old option specification methods or with the + new fluent interface API. + + * Deprecated <<<OptionParser.requiresArg()>>> in favor of + <<<OptionParser.requiredArg()>>> -- the new name seems to read better. + +Version 1.0 + + * First major release. + + * Includes concrete classes <<<OptionParser>>> and <<<OptionSet>>>. + + * Supports POSIX <<<getopt()>>> and GNU <<<getopt_long()>>> command line syntax. + + * No type conversion on option arguments, they are all treated as <<<String>>>s. + + * Methods <<<noArg()>>>, <<<requiredArg()>>>, and <<<optionalArg()>>> tell an + <<<OptionParser>>> what options to recognize. diff --git a/third_party/java/jopt-simple/src/site/apt/developer.apt b/third_party/java/jopt-simple/src/site/apt/developer.apt new file mode 100644 index 0000000000..59d5d82d5a --- /dev/null +++ b/third_party/java/jopt-simple/src/site/apt/developer.apt @@ -0,0 +1,48 @@ + -------------- + Developer Docs + -------------- + +Help for developing JOpt Simple + + This page has notes and hints for contributing to JOpt Simple, mostly around getting started and style questions. + +* Code Style + + Style is important. Why? Chiefly to aid merges. Reformatting code makes merging more difficult. When needing to reformat unchanged code, please do so on a separate commit with a clear commit message indicating a non-code change. + + In general use the Eclipse formatter (there is a plugin for IntelliJ IDEA). See <<<jopt-simple-eclipse-formatting.xml>>> and <<<jopt-simple.importorder>>> in the project root. + + The ultimate arbiter of good style is Paul Holser. + +** Braces + + * Yes: + ++----+ +for (int i = 0; i < 10; ++i) { + if (i < 5) + println(i); +} ++----+ + + * No: + ++----+ +for (int i = 0; i < 10; ++i) + if (i < 5) + println(i); ++----+ + +* {{Building}} + + There are no integration tests. Your typical command line is: + ++----+ +$ mvn clean test ++----+ + + Before pushing commits, please check that the site fully builds: + ++----+ +$ mvn clean post-site ++----+ diff --git a/third_party/java/jopt-simple/src/site/apt/download.apt.vm b/third_party/java/jopt-simple/src/site/apt/download.apt.vm new file mode 100644 index 0000000000..dde9015f5e --- /dev/null +++ b/third_party/java/jopt-simple/src/site/apt/download.apt.vm @@ -0,0 +1,26 @@ + -------- + Download + -------- + + Releases of JOpt Simple are synced to the central Maven repository. Declare a + dependency element in your POM like so: + ++--------------------------------------------- +... +<dependencies> + ... + <dependency> + <groupId>net.sf.jopt-simple</groupId> + <artifactId>jopt-simple</artifactId> + <version>${project.version}</version> + </dependency> + ... +</dependencies> +... ++--------------------------------------------- + + If you're not using Maven, you can still download the newer releases from the Maven + repository manually, {{{http://repo1.maven.org/maven2/net/sf/jopt-simple/jopt-simple} here}}. + + You can find older releases at + {{{http://sourceforge.net/project/showfiles.php?group_id=125731} SourceForge}}. diff --git a/third_party/java/jopt-simple/src/site/apt/examples.apt b/third_party/java/jopt-simple/src/site/apt/examples.apt new file mode 100644 index 0000000000..3b43dee995 --- /dev/null +++ b/third_party/java/jopt-simple/src/site/apt/examples.apt @@ -0,0 +1,462 @@ + ----------------- + Examples of Usage + ----------------- + +Preamble + + The simplicity in JOpt "Simple" arises from two guiding principles: + + * Stick as often as possible to supporting conventional Unix option syntaxes. + + * Keep the surface area of the published API as small and simple as possible. + + [] + + To the first principle: You will not see support in JOpt Simple for option "groups", + alternative option prefixes (<<<+>>>, <<</>>>), enforced multiplicity of option + arguments, etc. JOpt Simple believes you can create a useful and understandable CLI + without all that stuff. If you feel as though you need any of those features, there + are lots of other choices out there. The author of JOpt Simple believes you'll want + to leverage its easy configuration, parsing, and option interrogation APIs instead of + using more feature-laden, but perhaps more confusing libraries. + + To the second principle: JOpt Simple will make every attempt to keep the API free + of clutter. The API is well factored, making it intuitive to use, and the entire + library is well tested, making it more reliable and predictable. If you cannot look + at the Javadoc and quickly get a sense of what you need to do to use JOpt Simple, + then JOpt Simple has failed. So by all means, let the author know what needs + improved. + + With that said, let's take a tour through JOpt Simple's features. + +Options + + JOpt Simple supports short options and long options, using a syntax that attempts to + take from the best of POSIX <<<getopt()>>> and GNU <<<getopt_long()>>>. + +* Short Options + + Short options begin with a single hyphen (<<<->>>) followed by a single letter or + digit, or question mark (<<<?>>>), or dot (<<<.>>>). + ++---------------------------------------------------------------------------------------- +@SHORT_OPTIONS_EXAMPLE@ ++---------------------------------------------------------------------------------------- + + When you construct an <<<OptionParser>>> with a string of short option characters, + you configure that parser to recognize the options with those characters. + +** Arguments of Options + + Short options can accept single arguments. The argument can be made required or + optional. When you construct an <<<OptionParser>>> with a string of short option + characters, append a single colon (<<<:>>>) to an option character to configure + that option to require an argument. Append two colons (<<<::>>>) to an option + character to configure that option to accept an optional argument. Append an + asterisk (<<<*>>>) to an option character, but before any "argument" indicators, + to configure that option as a "help" option. + + The syntax of the option specification string given to the <<<OptionParser>>> + constructor should look familiar to you if you have used GNU's <<<getopt()>>> + before. + ++---------------------------------------------------------------------------------------- +@SHORT_OPTIONS_WITH_ARGUMENTS_EXAMPLE@ ++---------------------------------------------------------------------------------------- + +*** Specifying Arguments for a Short Option on the Command Line + + A short option's argument can occur: + + * in the position on the command line after the option + + * right up against the option + + * right up against the option separated by an equals sign (<<<=>>>) + + [] + ++---------------------------------------------------------------------------------------- +@SHORT_OPTIONS_WITH_ARGUMENT_POSITIONING_EXAMPLE@ ++---------------------------------------------------------------------------------------- + +*** Multiple Arguments for a Single Option + + To specify <n> arguments for a single option, specify the option <n> times on the + command line, once for each argument. JOpt Simple reports the arguments given to the + option in the order in which they were encountered on the command line. + ++---------------------------------------------------------------------------------------- +@SHORT_OPTIONS_WITH_MULTIPLE_ARGUMENTS_FOR_SINGLE_OPTION_EXAMPLE@ ++---------------------------------------------------------------------------------------- + +** Clustering Short Options + + Short options can be <clustered> in a single argument. + ++---------------------------------------------------------------------------------------- +@SHORT_OPTIONS_CLUSTERING_EXAMPLE@ ++---------------------------------------------------------------------------------------- + + If one of the short options can accept an argument, the remaining characters are interpreted + as the argument for that option. + ++---------------------------------------------------------------------------------------- +@SHORT_OPTIONS_CLUSTERING_WITH_ARGUMENT_EXAMPLE@ ++---------------------------------------------------------------------------------------- + +* Long Options/Fluent Interface + + Long options begin with two hyphens (<<<-->>>), followed by multiple letters, + digits, hyphens, question marks, or dots. A hyphen cannot be the first character of + a long option specification when configuring the parser. + + Whereas short options can be configured using a constructor argument to + <<<OptionParser>>>, both long and short options can be configured using a "fluent + interface" API, that enables some very descriptive and powerful features. + ++---------------------------------------------------------------------------------------- +@LONG_OPTIONS_EXAMPLE@ ++---------------------------------------------------------------------------------------- + +** Arguments of Options + + Like short options, long options can accept single arguments. The argument can be + made required or optional. Use the methods <<<withRequiredArg()>>> and + <<<withOptionalArg()>>> on the return value of <<<OptionParser.accepts()>>> to signal + that an option takes a required or optional argument. + ++---------------------------------------------------------------------------------------- +@LONG_OPTIONS_WITH_ARGUMENTS_EXAMPLE@ ++---------------------------------------------------------------------------------------- + +** Abbreviating Long Options + + Notice in the example above that the command line uses abbreviations of command line + options. You can abbreviate options so long as the abbreviation is unambiguous. + Even though you can abbreviate the options on the command line, you cannot address + the <<<OptionSet>>> using those abbreviations. You can use a special constructor + for the <<<OptionParser>>> that turns off abbreviation matching. + +** Using Single Hyphen on Long Options + + As demonstrated in the example above, you can use a single hyphen instead of a + double hyphen to specify a long option -- but be careful that doing so doesn't + introduce ambiguity. + +*** Specifying Arguments for a Long Option on the Command Line + + A long option's argument can occur: + + * in the position on the command line after the option + + * right up against the option separated by an equals sign (<<<=>>>) + + [] + ++---------------------------------------------------------------------------------------- +@LONG_OPTIONS_WITH_ARGUMENT_POSITIONING_EXAMPLE@ ++---------------------------------------------------------------------------------------- + +*** Multiple Arguments for a Single Option + + Specify multiple arguments for a long option in the same manner as for short options + (see above). + +** Alternative Form of Long Options + + The option <<<-W>>> is reserved. If you tell the parser to recognize alternative + long options, then it will treat, for example, <<<-W foo=bar>>> as the long option + <<<foo>>> with argument bar, as though you had written <<<--foo=bar>>>. + + You can specify <<<-W>>> as a valid short option, or use it as an abbreviation for a + long option, but recognizing alternative long options will always supersede this + behavior. + + To recognize alternative long options, either construct an <<<OptionParser>>> with a + string of short option characters containing the sequence <<<W;>>> (a capital W + followed by a semicolon), or call the method + <<<OptionParser.recognizeAlternativeLongOptions()>>>. + ++---------------------------------------------------------------------------------------- +@ALTERNATIVE_LONG_OPTIONS_EXAMPLE@ ++---------------------------------------------------------------------------------------- + +* Other Features + +** Converting Option Arguments to Other Types + + Without action other than the <<<with*Arg()>>> methods, arguments of options are + returned as <<<String>>>s. For backwards compatibility, + <<<OptionSet.valueOf(String)>>> and <<<OptionSet.valuesOf(String)>>> return + <<<Object>>> and <<<List<?>>>>, respectively, so to get the values out as + <<<String>>>s, you will need to downcast the results of those methods. + + You can tell JOpt Simple to convert the arguments of options to different Java types + via the <<<ofType()>>> method on the return value of <<<with*Arg()>>>. The + <<<Class>>> argument of <<<ofType()>>> must represent a Java class that has either: + + * a <<<public static>>> method called <<<valueOf()>>> which accepts a single + <<<String>>> argument and whose return type is the type itself, or + + * a <<<public>>> constructor which takes a single <<<String>>> argument. + + [] + + If the class has both, the <<<valueOf()>>> method is used. + + Note that <<<enum>>>s have a <<<valueOf()>>> method. + ++---------------------------------------------------------------------------------------- +@OPTION_ARGUMENT_VALUE_TYPE_EXAMPLE@ ++---------------------------------------------------------------------------------------- + + Another way to convert arguments of options is to specify a converter object via + <<<withValuesConvertedBy()>>>. This is useful when the desired type for the arguments + does not meet the requirements that <<<ofType()>>> sets forth. Such objects may not + perform any "conversion" at all, but rather can validate that arguments conform to + certain restrictions before passing through as-is. + + You can also do this for the non-option arguments of your command line, if you desire + to treat them all as a single type. + ++---------------------------------------------------------------------------------------- +@OPTION_ARGUMENT_CONVERTER_EXAMPLE@ ++---------------------------------------------------------------------------------------- + +** Retrieving Arguments of Options in a Type-Safe Manner + + In the previous examples, we have been discarding the return values of the methods + of JOpt Simple's fluent interface. If instead you retain them in variables of type + <<<OptionSpec>>>, you can use them to retrieve arguments of options in a type-safe + manner. + + You can also do this for the non-option arguments of your command line, if you desire + to treat them all as a single type. + ++---------------------------------------------------------------------------------------- +@TYPESAFE_OPTION_ARGUMENT_RETRIEVAL_EXAMPLE@ ++---------------------------------------------------------------------------------------- + +** Exporting Options and Arguments to other Code + + As an integration aid for other libraries, you can use <<<OptionSet.asMap()>>> to + obtain a mapping of <<<OptionSpec>>> to option values, for example to create a + properties map of options. + + Here is sample code to create properties whose keys have a common prefix. The key is + choosen as the first non-short option: + ++---------------------------------------------------------------------------------------- +@EXPORTING_OPTIONS_AND_ARGUMENTS_EXAMPLE@ ++---------------------------------------------------------------------------------------- + +** Default Values for Option Arguments + + Often it is convenient to specify default values for the arguments of certain + command line options. To do this, call the <<<defaultsTo()>>> method. + ++---------------------------------------------------------------------------------------- +@DEFAULT_VALUES_FOR_OPTION_ARGUMENTS_EXAMPLE@ ++---------------------------------------------------------------------------------------- + + You can see that <<<defaultsTo()>>> should relieve you of the burden of having to + check <<<has()>>> and/or <<<hasArgument()>>> on an <<<OptionSet>>> for a given option, + and has no bearing on the return values of those methods. Specifying a default value + for an option with a required argument does not mean that you can elide an argument for + the option on the command line. + + The type of values <<<defaultsTo()>>> expects is dictated by the class given by a + previous call to <<<ofType()>>> or <<<withValuesConvertedBy()>>>; if no such call has + been made, the type is <<<String>>>. + +** "Required" Options + + You can indicate that a given option must be present on the command line via the + <<<required()>>> method. Only options that accept arguments can be made "required". + + An option designated as a "help" option via <<<forHelp()>>>, when present on the + command line, causes missing "required" options not to reject the command line. + ++---------------------------------------------------------------------------------------- +@REQUIRED_OPTIONS_EXAMPLE@ ++---------------------------------------------------------------------------------------- + +** "Required" Dependent Options + + You can indicate that a given option must be present on the command line if some + other option is present on the command line via the <<<requiredIf()>>> method. + Any option can be made "required if". + + An option designated as a "help" option via <<<forHelp()>>>, when present on the + command line, causes missing "required if" options not to reject the command line. + ++---------------------------------------------------------------------------------------- +@REQUIRED_IF_OPTIONS_EXAMPLE@ ++---------------------------------------------------------------------------------------- + + You can also indicate that a given option must be present on the command line if some + other option is NOT present on the command line via the <<<requiredUnless()>>> method. + Any option can be made "required unless", but, to avoid potential conflicts, it should + not be "required if" at the same time. + ++---------------------------------------------------------------------------------------- +@REQUIRED_UNLESS_OPTIONS_EXAMPLE@ ++---------------------------------------------------------------------------------------- + +** "Available" Dependent Options + + Similarly to <<<requiredIf()>>> and <<<requiredUnless()>>>, you can indicate that a + given option can be present on the command line only if/unless some other option is + present on the command line, via the <<<availableIf()>>> and <<<availableUnless()>>> + methods. + + +** Synonyms of Options + + Sometimes it is useful to allow many different options to share the same meaning in + the program that uses them. To specify that options are to be treated as synonymous, + use the <<<acceptsAll()>>> method of <<<OptionParser>>>. + ++---------------------------------------------------------------------------------------- +@OPTION_SYNONYM_EXAMPLE@ ++---------------------------------------------------------------------------------------- + +** Concise Specification of Multiple Arguments for an Option + + Another way to specify multiple arguments for an option is to tell the parser to + treat a single argument containing multiple delimited values as multiple arguments + for the option using the <<<withValuesSeparatedBy()>>> method. + ++---------------------------------------------------------------------------------------- +@MULTIPLE_DELIMITED_ARGUMENTS_EXAMPLE@ ++---------------------------------------------------------------------------------------- + +** Signalling End of Options + + An argument consisting only of two hyphens (<<<-->>>) signals that the remaining + arguments are to be treated as non-options. + + An argument consisting only of a single hyphen is considered a non-option argument + (though it can be an argument of an option). Many Unix programs treat single hyphens + as stand-ins for the standard input or standard output stream. + +*** Non-Option Arguments + + Any arguments which are not options or arguments of options can be retrieved via + method <<<nonOptionArguments()>>> on <<<OptionSet>>>. If the double hyphen is an + argument, it is ignored and is not a non-option argument. + ++---------------------------------------------------------------------------------------- +@SIGNALLING_END_OF_OPTIONS_EXAMPLE@ ++---------------------------------------------------------------------------------------- + +** "POSIX-ly Correct"-ness + + By default, as with GNU <<<getopt()>>>, JOpt Simple allows intermixing of options and + non-options. If, however, the parser has been created to be "POSIX-ly correct", then + the first argument that does not look lexically like an option, and is not a required + argument of a preceding option, signals the end of options. You can still bind + optional arguments to their options using the abutting (for short options) or + <<<=>>> syntax. + + Unlike GNU <<<getopt()>>>, JOptSimple does not honor the environment variable + <<<POSIXLY_CORRECT>>>. "POSIX-ly correct" parsers are configured by either: + + * using the method <<<OptionParser.posixlyCorrect()>>> + + * using the <<<OptionParser>>> constructor with an argument whose first character is + a plus sign (<<<+>>>) + + [] + ++---------------------------------------------------------------------------------------- +@POSIXLY_CORRECT_EXAMPLE@ ++---------------------------------------------------------------------------------------- + +** Special Optional Argument Handling + + If the parser detects an option whose argument is optional, and the next argument + "looks like" an option, that argument is not treated as the argument to the option, + but as a potentially valid option. If, on the other hand, the optional argument is + typed as a derivative of <<<Number>>>, then that argument is treated as the negative + number argument of the option, even if the parser recognizes the corresponding numeric + option. + ++---------------------------------------------------------------------------------------- +@SPECIAL_OPTIONAL_ARGUMENT_HANDLING_EXAMPLE@ ++---------------------------------------------------------------------------------------- + +Generating Command Line Help + + When you call method <<<OptionParser.printHelpOn()>>>, JOpt Simple will write a + help screen (80-column width) describing all the options it is configured with, + along with types of option arguments, whether the option is required (in angle + brackets) or optional (in square brackets), etc. To give an option a description, + use <<<OptionParser.accepts*()>>> with a description argument. To give an option + argument a description, use <<<describedAs()>>> on the return value of + <<<with*Arg()>>>. + ++---------------------------------------------------------------------------------------- +@HELP_SCREEN_EXAMPLE@ ++---------------------------------------------------------------------------------------- + + Here is what the help screen looks like for the example above: + ++---------------------------------------------------------------------------------------- +@HELP_SCREEN_EXAMPLE_HELP@ ++---------------------------------------------------------------------------------------- + + If you want to create your own help screen, give method + <<<OptionParser.formatHelpWith()>>> a <<<HelpFormatter>>> that builds the help screen + as a String. When you call <<<OptionParser.printHelpOn()>>>, JOpt Simple will use + your <<<HelpFormatter>>> to produce the help and write it to the given stream. + + For example, this program: + ++---------------------------------------------------------------------------------------- +@HELP_FORMATTER_EXAMPLE@ ++---------------------------------------------------------------------------------------- + + yields the following output: + ++---------------------------------------------------------------------------------------- +@HELP_FORMATTER_EXAMPLE_OUTPUT@ ++---------------------------------------------------------------------------------------- + +Handling Exceptions + + JOpt Simple's classes raise some derivative of <<<OptionException>>> if they encounter + problems during parsing. These exceptions are unchecked, so you don't have to do + anything with such an exception if you don't want to. The rationale behind this + decision is that you will most likely be invoking JOpt Simple's functionality from a + <<<main()>>> method or very near to it, where a failure such as unrecognized arguments + can just stop down the JVM and yield a stack trace without much user or programmer + inconvenience. So, without any exception handling at all, a user would see something + like this: + ++---------------------------------------------------------------------------------------- +@EXAMPLE_STACK_TRACE@ ++---------------------------------------------------------------------------------------- + + If you want to handle the exception yourself, you can catch <<<OptionException>>> in + your code, and do whatever you please with the contents of the exception, perhaps + using the help generation facility. + +* Suppressing <<<UnrecognizedOptionException>>> + + Sometimes you want to ignore unrecognized options on the command line. + + For example, you might be interested in handling only a part of the arguments given. + Or you might want to pass on options to another program and not bother the user with + providing two hyphens (<<<-->>>) to indicate the end of known options. Or maybe + you want to provide future forwards/backwards compatibility when you foresee passing + in new options to old code (or old code invoking new code with "old" arguments). + + You can achieve this by using the method <<<OptionParser.allowsUnrecognizedOptions()>>>. + When you call this method, then any unrecognized options handed to <<<parse()>>> are + treated as non-option arguments, rather than causing an exception to be raised. + ++---------------------------------------------------------------------------------------- +@UNRECOGNIZED_OPTIONS_ALLOWED_EXAMPLE@ ++---------------------------------------------------------------------------------------- diff --git a/third_party/java/jopt-simple/src/site/apt/index.apt b/third_party/java/jopt-simple/src/site/apt/index.apt new file mode 100644 index 0000000000..88c2af858d --- /dev/null +++ b/third_party/java/jopt-simple/src/site/apt/index.apt @@ -0,0 +1,71 @@ + ----------- + JOpt Simple + ----------- + + JOpt Simple is a Java library for parsing command line options, such as those you + might pass to an invocation of <<<javac>>>. + + In the interest of striving for simplicity, as closely as possible JOpt Simple + attempts to honor the command line option syntaxes of + {{{http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html} POSIX <<<getopt()>>>}} + and + GNU {{{http://www.gnu.org/software/libc/manual/html_node/Getopt-Long-Options.html} <<<getopt_long()>>>}}. + It also aims to make option parser configuration and retrieval of options and their + arguments simple and expressive, without being overly clever. + + Here are some libraries that perform the same duties as JOpt Simple: + + * {{{http://jargs.sourceforge.net} JArgs}} + + * {{{http://jakarta.apache.org/commons/cli/} Jakarta Commons CLI}} + + * {{{http://te-code.sourceforge.net/} TE-Code}} has a command line parsing library. + + * {{{http://www.cs.ubc.ca/spider/lloyd/java/argparser.html} argparser}} + + * {{{http://www.urbanophile.com/arenn/hacking/download.html} Java port of GNU getopt}} + + * {{{https://args4j.dev.java.net/} Args4J}} + + * {{{http://www.martiansoftware.com/jsap/} JSAP}} + + * {{{http://clajr.sourceforge.net} CLAJR}} + + * {{{http://ostermiller.org/utils/CmdLn.html} CmdLn}} + + * {{{http://jewelcli.sourceforge.net} JewelCli}} + + * {{{http://jcommando.sourceforge.net} JCommando}} + + * {{{http://code.google.com/p/parse-cmd/} parse-cmd}} + + * {{{http://jcommander.org} JCommander}} + + * {{{http://types.cs.washington.edu/plume-lib/api/plume/Options.html} plume-lib Options}} + + [] + + I hope you'll agree that JOpt Simple tops them all in ease of use and cleanliness of + code (although I admire JewelCli quite a bit). + + I'd love to hear your constructive {{{mailto:pholser@alumni.rice.edu} feedback}}, + especially suggestions for improvements to the library or the site! If your project + is using JOpt Simple, do let me know. + +Projects Using JOpt Simple + + Here are some we know of or have known of: + + * {{{http://openjdk.java.net/} OpenJDK}}. + From {{{http://weblogs.java.net/blog/mreinhold/} Mark Reinhold}}: "I thought you might + be interested to know that we're using your jopt-simple library in the open-source + Java Development Kit. Thanks for writing such a nice little library! It's far + cleaner than any of the other alternatives out there." + + * {{{http://www.gradle.org/} Gradle}} + + * {{{http://natbraille.free.fr} NATBraille}} + + * {{{https://minecraft.net} Minecraft}} + + [] diff --git a/third_party/java/jopt-simple/src/site/resources/css/prettify.css b/third_party/java/jopt-simple/src/site/resources/css/prettify.css new file mode 100644 index 0000000000..f8c7db2a96 --- /dev/null +++ b/third_party/java/jopt-simple/src/site/resources/css/prettify.css @@ -0,0 +1,49 @@ +/* Pretty printing styles. Used with prettify.js. */ + +.str { color: #080; } +.kwd { color: #008; } +.com { color: #800; } +.typ { color: #606; } +.lit { color: #066; } +.pun { color: #660; } +.pln { color: #000; } +.tag { color: #008; } +.atn { color: #606; } +.atv { color: #080; } +.dec { color: #606; } + +pre.prettyprint { + padding: 2px; + border: 1px solid #888; +} + +@media print { + .str { color: #060; } + + .kwd { + color: #006; + font-weight: bold; + } + + .com { + color: #600; + font-style: italic; + } + + .typ { + color: #404; + font-weight: bold; + } + + .lit { color: #044; } + .pun { color: #440; } + .pln { color: #000; } + + .tag { + color: #006; + font-weight: bold; + } + + .atn { color: #404; } + .atv { color: #060; } +} diff --git a/third_party/java/jopt-simple/src/site/resources/images/jopt-simple-logo.png b/third_party/java/jopt-simple/src/site/resources/images/jopt-simple-logo.png Binary files differnew file mode 100644 index 0000000000..4a3f707d7a --- /dev/null +++ b/third_party/java/jopt-simple/src/site/resources/images/jopt-simple-logo.png diff --git a/third_party/java/jopt-simple/src/site/resources/scripts/prettify.js b/third_party/java/jopt-simple/src/site/resources/scripts/prettify.js new file mode 100644 index 0000000000..de1e07ffd3 --- /dev/null +++ b/third_party/java/jopt-simple/src/site/resources/scripts/prettify.js @@ -0,0 +1,1602 @@ +// Copyright (C) 2006 Google Inc. +// +// 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. + + +/** + * @fileoverview + * some functions for browser-side pretty printing of code contained in html. + * + * The lexer should work on a number of languages including C and friends, + * Java, Python, Bash, SQL, HTML, XML, CSS, Javascript, and Makefiles. + * It works passably on Ruby, PHP and Awk and a decent subset of Perl, but, + * because of commenting conventions, doesn't work on Smalltalk, Lisp-like, or + * CAML-like languages. + * + * If there's a language not mentioned here, then I don't know it, and don't + * know whether it works. If it has a C-like, Bash-like, or XML-like syntax + * then it should work passably. + * + * Usage: + * 1) include this source file in an html page via + * <script type="text/javascript" src="/path/to/prettify.js"></script> + * 2) define style rules. See the example page for examples. + * 3) mark the <pre> and <code> tags in your source with class=prettyprint. + * You can also use the (html deprecated) <xmp> tag, but the pretty printer + * needs to do more substantial DOM manipulations to support that, so some + * css styles may not be preserved. + * That's it. I wanted to keep the API as simple as possible, so there's no + * need to specify which language the code is in. + * + * Change log: + * cbeust, 2006/08/22 + * Java annotations (start with "@") are now captured as literals ("lit") + */ + +var PR_keywords = {}; +/** initialize the keyword list for our target languages. */ +(function () { + var CPP_KEYWORDS = "abstract bool break case catch char class const " + + "const_cast continue default delete deprecated dllexport dllimport do " + + "double dynamic_cast else enum explicit extern false float for friend " + + "goto if inline int long mutable naked namespace new noinline noreturn " + + "nothrow novtable operator private property protected public register " + + "reinterpret_cast return selectany short signed sizeof static " + + "static_cast struct switch template this thread throw true try typedef " + + "typeid typename union unsigned using declaration, directive uuid " + + "virtual void volatile while typeof"; + var CSHARP_KEYWORDS = "as base by byte checked decimal delegate descending " + + "event finally fixed foreach from group implicit in interface internal " + + "into is lock null object out override orderby params readonly ref sbyte " + + "sealed stackalloc string select uint ulong unchecked unsafe ushort var"; + var JAVA_KEYWORDS = "package synchronized boolean implements import throws " + + "instanceof transient extends final strictfp native super"; + var JSCRIPT_KEYWORDS = "debugger export function with NaN Infinity"; + var PERL_KEYWORDS = "require sub unless until use elsif BEGIN END"; + var PYTHON_KEYWORDS = "and assert def del elif except exec global lambda " + + "not or pass print raise yield False True None"; + var RUBY_KEYWORDS = "then end begin rescue ensure module when undef next " + + "redo retry alias defined"; + var SH_KEYWORDS = "done fi"; + + var KEYWORDS = [CPP_KEYWORDS, CSHARP_KEYWORDS, JAVA_KEYWORDS, + JSCRIPT_KEYWORDS, PERL_KEYWORDS, PYTHON_KEYWORDS, + RUBY_KEYWORDS, SH_KEYWORDS]; + for ( var k = 0; k < KEYWORDS.length; k++ ) { + var kw = KEYWORDS[k].split(' '); + for ( var i = 0; i < kw.length; i++ ) { + if ( kw[i] ) { + PR_keywords[kw[i]] = true; + } + } + } +}).call(this); + +// token style names. correspond to css classes +/** token style for a string literal */ +var PR_STRING = 'str'; +/** token style for a keyword */ +var PR_KEYWORD = 'kwd'; +/** token style for a comment */ +var PR_COMMENT = 'com'; +/** token style for a type */ +var PR_TYPE = 'typ'; +/** token style for a literal value. e.g. 1, null, true. */ +var PR_LITERAL = 'lit'; +/** token style for a punctuation string. */ +var PR_PUNCTUATION = 'pun'; +/** token style for a punctuation string. */ +var PR_PLAIN = 'pln'; + +/** token style for an sgml tag. */ +var PR_TAG = 'tag'; +/** token style for a markup declaration such as a DOCTYPE. */ +var PR_DECLARATION = 'dec'; +/** token style for embedded source. */ +var PR_SOURCE = 'src'; +/** token style for an sgml attribute name. */ +var PR_ATTRIB_NAME = 'atn'; +/** token style for an sgml attribute value. */ +var PR_ATTRIB_VALUE = 'atv'; + +/** the number of characters between tab columns */ +var PR_TAB_WIDTH = 8; + +/** the position of the end of a token during. A division of a string into + * n tokens can be represented as a series n - 1 token ends, as long as + * runs of whitespace warrant their own token. + * @private + */ +function PR_TokenEnd( end, style ) { + if ( undefined === style ) { + throw new Error('BAD'); + } + if ( 'number' != typeof(end) ) { + throw new Error('BAD'); + } + this.end = end; + this.style = style; +} +PR_TokenEnd.prototype.toString = function () { + return '[PR_TokenEnd ' + this.end + + (this.style ? ':' + this.style : '') + ']'; +}; + +/** a chunk of text with a style. These are used to represent both the output + * from the lexing functions as well as intermediate results. + * @constructor + * @param token the token text + * @param style one of the token styles defined in designdoc-template, or null + * for a styleless token, such as an embedded html tag. + * @private + */ +function PR_Token( token, style ) { + if ( undefined === style ) { + throw new Error('BAD'); + } + this.token = token; + this.style = style; +} + +PR_Token.prototype.toString = function () { + return '[PR_Token ' + this.token + (this.style ? ':' + this.style : '') + ']'; +}; + +/** a helper class that decodes common html entities used to escape special + * characters in source code. + * @constructor + * @private + */ +function PR_DecodeHelper() { + this.next = 0; + this.ch = '\0'; +} + +var PR_NAMED_ENTITIES = { + 'lt': '<', + 'gt': '>', + 'quot': '"', + 'apos': "'", + 'amp': '&' // reencoding requires that & always be decoded properly +}; + +PR_DecodeHelper.prototype.decode = function ( s, i ) { + var next = i + 1; + var ch = s.charAt(i); + if ( '&' === ch ) { + var semi = s.indexOf(';', next); + if ( semi >= 0 && semi < next + 4 ) { + var entityName = s.substring(next, semi); + var decoded = null; + if ( entityName.charAt(0) === '#' ) { // check for numeric entity + var ch1 = entityName.charAt(1); + var charCode; + if ( ch1 === 'x' || ch1 === 'X' ) { // like   + charCode = parseInt(entityName.substring(2), 16); + } + else { // like   + charCode = parseInt(entityName.substring(1), 10); + } + if ( !isNaN(charCode) ) { + decoded = String.fromCharCode(charCode); + } + } + if ( !decoded ) { + decoded = PR_NAMED_ENTITIES[entityName.toLowerCase()]; + } + if ( decoded ) { + ch = decoded; + next = semi + 1; + } + else { // skip over unrecognized entity + next = i + 1; + ch = '\0'; + } + } + } + this.next = next; + this.ch = ch; + return this.ch; +}; + +// some string utilities +function PR_isWordChar( ch ) { + return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'); +} + +function PR_isIdentifierStart( ch ) { + return PR_isWordChar(ch) || ch == '_' || ch == '$' || ch == '@'; +} + +function PR_isIdentifierPart( ch ) { + return PR_isIdentifierStart(ch) || PR_isDigitChar(ch); +} + +function PR_isSpaceChar( ch ) { + return "\t \r\n".indexOf(ch) >= 0; +} + +function PR_isDigitChar( ch ) { + return ch >= '0' && ch <= '9'; +} + +function PR_trim( s ) { + var i = 0, j = s.length - 1; + while ( i <= j && PR_isSpaceChar(s.charAt(i)) ) { + ++i; + } + while ( j > i && PR_isSpaceChar(s.charAt(j)) ) { + --j; + } + return s.substring(i, j + 1); +} + +function PR_startsWith( s, prefix ) { + return s.length >= prefix.length && prefix == s.substring(0, prefix.length); +} + +function PR_endsWith( s, suffix ) { + return s.length >= suffix.length && + suffix == s.substring(s.length - suffix.length, s.length); +} + +/** true iff prefix matches the first prefix characters in chars[0:len]. + * @private + */ +function PR_prefixMatch( chars, len, prefix ) { + if ( len < prefix.length ) { + return false; + } + for ( var i = 0, n = prefix.length; i < n; ++i ) { + if ( prefix.charAt(i) != chars[i] ) { + return false; + } + } + return true; +} + +/** like textToHtml but escapes double quotes to be attribute safe. */ +function PR_attribToHtml( str ) { + return str.replace(/&/g, '&') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/\"/g, '"') + .replace(/\xa0/, ' '); +} + +/** escapest html special characters to html. */ +function PR_textToHtml( str ) { + return str.replace(/&/g, '&') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/\xa0/g, ' '); +} + +/** is the given node's innerHTML normally unescaped? */ +function PR_isRawContent( node ) { + return 'XMP' == node.tagName; +} + +var PR_innerHtmlWorks = null; +function PR_getInnerHtml( node ) { + // inner html is hopelessly broken in Safari 2.0.4 when the content is + // an html description of well formed XML and the containing tag is a PRE + // tag, so we detect that case and emulate innerHTML. + if ( null == PR_innerHtmlWorks ) { + var testNode = document.createElement('PRE'); + testNode.appendChild( + document.createTextNode('<!DOCTYPE foo PUBLIC "foo bar">\n<foo />')); + PR_innerHtmlWorks = !/</.test(testNode.innerHTML); + } + + if ( PR_innerHtmlWorks ) { + var content = node.innerHTML; + // XMP tags contain unescaped entities so require special handling. + if ( PR_isRawContent(node) ) { + content = PR_textToHtml(content); + } + return content; + } + + var out = []; + for ( var child = node.firstChild; child; child = child.nextSibling ) { + PR_normalizedHtml(child, out); + } + return out.join(''); +} + +/** + * walks the DOM returning a properly escaped version of innerHTML. + */ +function PR_normalizedHtml( node, out ) { + switch ( node.nodeType ) { + case 1: // an element + var name = node.tagName.toLowerCase(); + out.push('\074', name); + for ( var i = 0; i < node.attributes.length; ++i ) { + var attr = node.attributes[i]; + if ( !attr.specified ) { + continue; + } + out.push(' '); + PR_normalizedHtml(attr, out); + } + out.push('>'); + for ( var child = node.firstChild; child; child = child.nextSibling ) { + PR_normalizedHtml(child, out); + } + if ( node.firstChild || !/^(?:br|link|img)$/.test(name) ) { + out.push('<\/', name, '>'); + } + break; + case 2: // an attribute + out.push(node.name.toLowerCase(), '="', PR_attribToHtml(node.value), '"'); + break; + case 3: case 4: // text + out.push(PR_textToHtml(node.nodeValue)); + break; + } +} + +/** expand tabs to spaces + * @param {Array} chunks PR_Tokens possibly containing tabs + * @param {Number} tabWidth number of spaces between tab columns + * @return {Array} chunks with tabs replaced with spaces + */ +function PR_expandTabs( chunks, tabWidth ) { + var SPACES = ' '; + + var charInLine = 0; + var decodeHelper = new PR_DecodeHelper(); + + var chunksOut = [] + for ( var chunkIndex = 0; chunkIndex < chunks.length; ++chunkIndex ) { + var chunk = chunks[chunkIndex]; + if ( chunk.style == null ) { + chunksOut.push(chunk); + continue; + } + + var s = chunk.token; + var pos = 0; + // index of last character output + var out = []; + + // walk over each character looking for tabs and newlines. + // On tabs, expand them. On newlines, reset charInLine. + // Otherwise increment charInLine + for ( var charIndex = 0, n = s.length; charIndex < n; + charIndex = decodeHelper.next ) { + decodeHelper.decode(s, charIndex); + var ch = decodeHelper.ch; + + switch ( ch ) { + case '\t': + out.push(s.substring(pos, charIndex)); + // calculate how much space we need in front of this part + // nSpaces is the amount of padding -- the number of spaces needed to + // move us to the next column, where columns occur at factors of + // tabWidth. + var nSpaces = tabWidth - (charInLine % tabWidth); + charInLine += nSpaces; + for ( ; nSpaces >= 0; nSpaces -= SPACES.length ) { + out.push(SPACES.substring(0, nSpaces)); + } + pos = decodeHelper.next; + break; + case '\n': case '\r': + charInLine = 0; + break; + default: + ++charInLine; + } + } + out.push(s.substring(pos)); + chunksOut.push(new PR_Token(out.join(''), chunk.style)); + } + return chunksOut +} + +/** split markup into chunks of html tags (style null) and + * plain text (style {@link #PR_PLAIN}). + * + * @param {String} s html. + * @return {Array} of PR_Tokens of style PR_PLAIN, and null. + * @private + */ +function PR_chunkify( s ) { + // The below pattern matches one of the following + // (1) /[^<]+/ : A run of characters other than '<' + // (2) /<\/?[a-zA-Z][^>]*>/ : A probably tag that should not be highlighted + // (3) /</ : A '<' that does not begin a larger chunk. Treated as 1 + var chunkPattern = /(?:[^<]+|<\/?[a-zA-Z][^>]*>|<)/g; + // since the pattern has the 'g' modifier and defines no capturing groups, + // this will return a list of all chunks which we then classify and wrap as + // PR_Tokens + var matches = s.match(chunkPattern); + var chunks = []; + if ( matches ) { + var lastChunk = null; + for ( var i = 0, n = matches.length; i < n; ++i ) { + var chunkText = matches[i]; + var style; + if ( chunkText.length < 2 || chunkText.charAt(0) !== '<' ) { + if ( lastChunk && lastChunk.style === PR_PLAIN ) { + lastChunk.token += chunkText; + continue; + } + style = PR_PLAIN; + } + else { // a tag + style = null; + } + lastChunk = new PR_Token(chunkText, style); + chunks.push(lastChunk); + } + } + return chunks; +} + +/** walk the tokenEnds list and the chunk list in parallel to generate a list + * of split tokens. + * @private + */ +function PR_splitChunks( chunks, tokenEnds ) { + var tokens = []; + // the output + + var ci = 0; + // index into chunks + // position of beginning of amount written so far in absolute space. + var posAbs = 0; + // position of amount written so far in chunk space + var posChunk = 0; + + // current chunk + var chunk = new PR_Token('', null); + + for ( var ei = 0, ne = tokenEnds.length, lastEnd = 0; ei < ne; ++ei ) { + var tokenEnd = tokenEnds[ei]; + var end = tokenEnd.end; + if ( end === lastEnd ) { + continue; + } // skip empty regions + + var tokLen = end - posAbs; + var remainingInChunk = chunk.token.length - posChunk; + while ( remainingInChunk <= tokLen ) { + if ( remainingInChunk > 0 ) { + tokens.push( + new PR_Token(chunk.token.substring(posChunk, chunk.token.length), + null == chunk.style ? null : tokenEnd.style)); + } + posAbs += remainingInChunk; + posChunk = 0; + if ( ci < chunks.length ) { + chunk = chunks[ci++]; + } + + tokLen = end - posAbs; + remainingInChunk = chunk.token.length - posChunk; + } + + if ( tokLen ) { + tokens.push( + new PR_Token(chunk.token.substring(posChunk, posChunk + tokLen), + tokenEnd.style)); + posAbs += tokLen; + posChunk += tokLen; + } + } + + return tokens; +} + +/** splits markup tokens into declarations, tags, and source chunks. + * @private + */ +function PR_splitMarkup( chunks ) { + // A state machine to split out declarations, tags, etc. + // This state machine deals with absolute space in the text, indexed by k, + // and position in the current chunk, indexed by pos and tokenStart to + // generate a list of the ends of tokens. + // Absolute space is calculated by considering the chunks as appended into + // one big string, as they were before being split. + + // Known failure cases + // Server side scripting sections such as <?...?> in attributes. + // i.e. <span class="<? foo ?>"> + // Handling this would require a stack, and we don't use PHP. + + // The output: a list of pairs of PR_TokenEnd instances + var tokenEnds = []; + + var state = 0; + // FSM state variable + var k = 0; + // position in absolute space of the start of the current chunk + var tokenStart = -1; + // the start of the current token + + // Try to find a closing tag for any open <style> or <script> tags + // We can't do this at a later stage because then the following case + // would fail: + // <script>document.writeln('<!--');</script> + + // We use tokenChars[:tokenCharsI] to accumulate the tag name so that we + // can check whether to enter into a no scripting section when the tag ends. + var tokenChars = new Array(12); + var tokenCharsI = 0; + // if non null, the tag prefix that we need to see to break out. + var endScriptTag = null; + var decodeHelper = new PR_DecodeHelper(); + + for ( var ci = 0, nc = chunks.length; ci < nc; ++ci ) { + var chunk = chunks[ci]; + if ( PR_PLAIN != chunk.style ) { + k += chunk.token.length; + continue; + } + + var s = chunk.token; + var pos = 0; + // the position past the last character processed so far in s + + for ( var i = 0, n = s.length; i < n; /* i = next at bottom */ ) { + decodeHelper.decode(s, i); + var ch = decodeHelper.ch; + var next = decodeHelper.next; + + var tokenStyle = null; + switch ( state ) { + case 0: + if ( '<' == ch ) { + state = 1; + } + break; + case 1: + tokenCharsI = 0; + if ( '/' == ch ) { // only consider close tags if we're in script/style + state = 7; + } + else if ( null == endScriptTag ) { + if ( '!' == ch ) { + state = 2; + } + else if ( PR_isWordChar(ch) ) { + state = 8; + } + else if ( '?' == ch ) { + state = 9; + } + else if ( '%' == ch ) { + state = 11; + } + else if ( '<' != ch ) { + state = 0; + } + } + else if ( '<' != ch ) { + state = 0; + } + break; + case 2: + if ( '-' == ch ) { + state = 4; + } + else if ( PR_isWordChar(ch) ) { + state = 3; + } + else if ( '<' == ch ) { + state = 1; + } + else { + state = 0; + } + break; + case 3: + if ( '>' == ch ) { + state = 0; + tokenStyle = PR_DECLARATION; + } + break; + case 4: + if ( '-' == ch ) { + state = 5; + } + break; + case 5: + if ( '-' == ch ) { + state = 6; + } + break; + case 6: + if ( '>' == ch ) { + state = 0; + tokenStyle = PR_COMMENT; + } + else if ( '-' == ch ) { + state = 6; + } + else { + state = 4; + } + break; + case 7: + if ( PR_isWordChar(ch) ) { + state = 8; + } + else if ( '<' == ch ) { + state = 1; + } + else { + state = 0; + } + break; + case 8: + if ( '>' == ch ) { + state = 0; + tokenStyle = PR_TAG; + } + break; + case 9: + if ( '?' == ch ) { + state = 10; + } + break; + case 10: + if ( '>' == ch ) { + state = 0; + tokenStyle = PR_SOURCE; + } + else if ( '?' != ch ) { + state = 9; + } + break; + case 11: + if ( '%' == ch ) { + state = 12; + } + break; + case 12: + if ( '>' == ch ) { + state = 0; + tokenStyle = PR_SOURCE; + } + else if ( '%' != ch ) { + state = 11; + } + break; + } + + if ( tokenCharsI < tokenChars.length ) { + tokenChars[tokenCharsI++] = ch.toLowerCase(); + } + if ( 1 == state ) { + tokenStart = k + i; + } + i = next; + if ( tokenStyle != null ) { + if ( null != tokenStyle ) { + if ( endScriptTag ) { + if ( PR_prefixMatch(tokenChars, tokenCharsI, endScriptTag) ) { + endScriptTag = null; + } + } + else { + if ( PR_prefixMatch(tokenChars, tokenCharsI, 'script') ) { + endScriptTag = '/script'; + } + else if ( PR_prefixMatch(tokenChars, tokenCharsI, 'style') ) { + endScriptTag = '/style'; + } + else if ( PR_prefixMatch(tokenChars, tokenCharsI, 'xmp') ) { + endScriptTag = '/xmp'; + } + } + // disallow the tag if endScriptTag is set and this was not an open + // tag. + if ( endScriptTag && tokenCharsI && '/' == tokenChars[0] ) { + tokenStyle = null; + } + } + if ( null != tokenStyle ) { + tokenEnds.push(new PR_TokenEnd(tokenStart, PR_PLAIN)); + tokenEnds.push(new PR_TokenEnd(k + next, tokenStyle)); + } + } + } + k += chunk.token.length; + } + tokenEnds.push(new PR_TokenEnd(k, PR_PLAIN)); + + return tokenEnds; +} + +/** splits the given string into comment, string, and "other" tokens. + * @return {Array} of PR_Tokens with style in + * (PR_STRING, PR_COMMENT, PR_PLAIN, null) + * The result array may contain spurious zero length tokens. Ignore them. + * + * @private + */ +function PR_splitStringAndCommentTokens( chunks ) { + // a state machine to split out comments, strings, and other stuff + var tokenEnds = []; + // positions of ends of tokens in absolute space + var state = 0; + // FSM state variable + var delim = -1; + // string delimiter + var k = 0; + // absolute position of beginning of current chunk + + for ( var ci = 0, nc = chunks.length; ci < nc; ++ci ) { + var chunk = chunks[ci]; + var s = chunk.token; + if ( PR_PLAIN == chunk.style ) { + var decodeHelper = new PR_DecodeHelper(); + var last = -1; + var next; + for ( var i = 0, n = s.length; i < n; last = i,i = next ) { + decodeHelper.decode(s, i); + var ch = decodeHelper.ch; + next = decodeHelper.next; + if ( 0 == state ) { + if ( ch == '"' || ch == '\'' || ch == '`' ) { + tokenEnds.push(new PR_TokenEnd(k + i, PR_PLAIN)); + state = 1; + delim = ch; + } + else if ( ch == '/' ) { + state = 3; + } + else if ( ch == '#' ) { + tokenEnds.push(new PR_TokenEnd(k + i, PR_PLAIN)); + state = 4; + } + } + else if ( 1 == state ) { + if ( ch == delim ) { + state = 0; + tokenEnds.push(new PR_TokenEnd(k + next, PR_STRING)); + } + else if ( ch == '\\' ) { + state = 2; + } + } + else if ( 2 == state ) { + state = 1; + } + else if ( 3 == state ) { + if ( ch == '/' ) { + state = 4; + tokenEnds.push(new PR_TokenEnd(k + last, PR_PLAIN)); + } + else if ( ch == '*' ) { + state = 5; + tokenEnds.push(new PR_TokenEnd(k + last, PR_PLAIN)); + } + else { + state = 0; + // next loop will reenter state 0 without same value of i, so + // ch will be reconsidered as start of new token. + next = i; + } + } + else if ( 4 == state ) { + if ( ch == '\r' || ch == '\n' ) { + state = 0; + tokenEnds.push(new PR_TokenEnd(k + i, PR_COMMENT)); + } + } + else if ( 5 == state ) { + if ( ch == '*' ) { + state = 6; + } + } + else if ( 6 == state ) { + if ( ch == '/' ) { + state = 0; + tokenEnds.push(new PR_TokenEnd(k + next, PR_COMMENT)); + } + else if ( ch != '*' ) { + state = 5; + } + } + } + } + k += s.length; + } + var endTokenType; + switch ( state ) { + case 1: case 2: + endTokenType = PR_STRING; + break; + case 4: case 5: case 6: + endTokenType = PR_COMMENT; + break; + default: + endTokenType = PR_PLAIN; + break; + } + // handle unclosed token which can legally happen for line comments (state 4) + tokenEnds.push(new PR_TokenEnd(k, endTokenType)); + // a token ends at the end + + return PR_splitChunks(chunks, tokenEnds); +} + +/** used by lexSource to split a non string, non comment token. + * @private + */ +function PR_splitNonStringNonCommentToken( s, outlist ) { + var pos = 0; + var state = 0; + + var decodeHelper = new PR_DecodeHelper(); + var next; + for ( var i = 0; i <= s.length; i = next ) { + if ( i == s.length ) { + // nstate will not be equal to state, so it will append the token + nstate = -2; + next = i + 1; + } + else { + decodeHelper.decode(s, i); + next = decodeHelper.next; + var ch = decodeHelper.ch; + + // the next state. + // if set to -1 then it will cause a reentry to state 0 without consuming + // another character. + var nstate = state; + + switch ( state ) { + case 0: // whitespace state + if ( PR_isIdentifierStart(ch) ) { + nstate = 1; + } + else if ( PR_isDigitChar(ch) ) { + nstate = 2; + } + else if ( !PR_isSpaceChar(ch) ) { + nstate = 3; + } + if ( nstate && pos < i ) { + var t = s.substring(pos, i); + outlist.push(new PR_Token(t, PR_PLAIN)); + pos = i; + } + break; + case 1: // identifier state + if ( !PR_isIdentifierPart(ch) ) { + nstate = -1; + } + break; + case 2: // number literal state + // handle numeric literals like + // 0x7f 300UL 100_000 + + // this does not treat floating point values as a single literal + // 0.1 and 3e-6 + // are each split into multiple tokens + if ( !(PR_isDigitChar(ch) || PR_isWordChar(ch) || ch == '_') ) { + nstate = -1; + } + break; + case 3: // punctuation state + if ( PR_isIdentifierStart(ch) || PR_isDigitChar(ch) || + PR_isSpaceChar(ch) ) { + nstate = -1; + } + break; + } + } + + if ( nstate != state ) { + if ( nstate < 0 ) { + if ( i > pos ) { + var t = s.substring(pos, i); + var wordDecodeHelper = new PR_DecodeHelper(); + wordDecodeHelper.decode(t, 0); + var ch0 = wordDecodeHelper.ch; + var isSingleCharacter = wordDecodeHelper.next == t.length; + var style; + if ( PR_isIdentifierStart(ch0) ) { + if ( PR_keywords[t] ) { + style = PR_KEYWORD; + } + else if ( ch0 === '@' ) { + style = PR_LITERAL; + } + else { + // Treat any word that starts with an uppercase character and + // contains at least one lowercase character as a type, or + // ends with _t. + // This works perfectly for Java, pretty well for C++, and + // passably for Python. The _t catches C structs. + var isType = false; + if ( ch0 >= 'A' && ch0 <= 'Z' ) { + for ( var j = wordDecodeHelper.next; + j < t.length; j = wordDecodeHelper.next ) { + wordDecodeHelper.decode(t, j); + var ch1 = wordDecodeHelper.ch; + if ( ch1 >= 'a' && ch1 <= 'z' ) { + isType = true; + break; + } + } + if ( !isType && !isSingleCharacter && + t.substring(t.length - 2) == '_t' ) { + isType = true; + } + } + style = isType ? PR_TYPE : PR_PLAIN; + } + } + else if ( PR_isDigitChar(ch0) ) { + style = PR_LITERAL; + } + else if ( !PR_isSpaceChar(ch0) ) { + style = PR_PUNCTUATION; + } + else { + style = PR_PLAIN; + } + pos = i; + outlist.push(new PR_Token(t, style)); + } + + state = 0; + if ( nstate == -1 ) { + // don't increment. This allows us to use state 0 to redispatch based + // on the current character. + next = i; + continue; + } + } + state = nstate; + } + } + +} + +/** split a group of chunks of markup. + * @private + */ +function PR_tokenizeMarkup( chunks ) { + if ( !(chunks && chunks.length) ) { + return chunks; + } + + var tokenEnds = PR_splitMarkup(chunks); + return PR_splitChunks(chunks, tokenEnds); +} + +/** split tags attributes and their values out from the tag name, and + * recursively lex source chunks. + * @private + */ +function PR_splitTagAttributes( tokens ) { + var tokensOut = []; + var state = 0; + var stateStyle = PR_TAG; + var delim = null; + // attribute delimiter for quoted value state. + var decodeHelper = new PR_DecodeHelper(); + for ( var ci = 0; ci < tokens.length; ++ci ) { + var tok = tokens[ci]; + if ( PR_TAG == tok.style ) { + var s = tok.token; + var start = 0; + for ( var i = 0; i < s.length; /* i = next at bottom */ ) { + decodeHelper.decode(s, i); + var ch = decodeHelper.ch; + var next = decodeHelper.next; + + var emitEnd = null; + // null or position of end of chunk to emit. + var nextStyle = null; + // null or next value of stateStyle + if ( ch == '>' ) { + if ( PR_TAG != stateStyle ) { + emitEnd = i; + nextStyle = PR_TAG; + } + } + else { + switch ( state ) { + case 0: + if ( '<' == ch ) { + state = 1; + } + break; + case 1: + if ( PR_isSpaceChar(ch) ) { + state = 2; + } + break; + case 2: + if ( !PR_isSpaceChar(ch) ) { + nextStyle = PR_ATTRIB_NAME; + emitEnd = i; + state = 3; + } + break; + case 3: + if ( '=' == ch ) { + emitEnd = i; + nextStyle = PR_TAG; + state = 5; + } + else if ( PR_isSpaceChar(ch) ) { + emitEnd = i; + nextStyle = PR_TAG; + state = 4; + } + break; + case 4: + if ( '=' == ch ) { + state = 5; + } + else if ( !PR_isSpaceChar(ch) ) { + emitEnd = i; + nextStyle = PR_ATTRIB_NAME; + state = 3; + } + break; + case 5: + if ( '"' == ch || '\'' == ch ) { + emitEnd = i; + nextStyle = PR_ATTRIB_VALUE; + state = 6; + delim = ch; + } + else if ( !PR_isSpaceChar(ch) ) { + emitEnd = i; + nextStyle = PR_ATTRIB_VALUE; + state = 7; + } + break; + case 6: + if ( ch == delim ) { + emitEnd = next; + nextStyle = PR_TAG; + state = 2; + } + break; + case 7: + if ( PR_isSpaceChar(ch) ) { + emitEnd = i; + nextStyle = PR_TAG; + state = 2; + } + break; + } + } + if ( emitEnd ) { + if ( emitEnd > start ) { + tokensOut.push( + new PR_Token(s.substring(start, emitEnd), stateStyle)); + start = emitEnd; + } + stateStyle = nextStyle; + } + i = next; + } + if ( s.length > start ) { + tokensOut.push(new PR_Token(s.substring(start, s.length), stateStyle)); + } + } + else { + if ( tok.style ) { + state = 0; + stateStyle = PR_TAG; + } + tokensOut.push(tok); + } + } + return tokensOut; +} + +/** identify regions of markup that are really source code, and recursivley + * lex them. + * @private + */ +function PR_splitSourceNodes( tokens ) { + var tokensOut = []; + // when we see a <script> tag, store '/' here so that we know to end the + // source processing + var endScriptTag = null; + var decodeHelper = new PR_DecodeHelper(); + + var sourceChunks = null; + + for ( var ci = 0, nc = tokens.length; /* break below */; ++ci ) { + var tok; + + if ( ci < nc ) { + tok = tokens[ci]; + if ( null == tok.style ) { + tokens.push(tok); + continue; + } + } + else if ( !endScriptTag ) { + break; + } + else { + // else pretend there's an end tag so we can gracefully handle + // unclosed source blocks + tok = new PR_Token('', null); + } + + var s = tok.token; + + if ( null == endScriptTag ) { + if ( PR_SOURCE == tok.style ) { + // split off any starting and trailing <?, <% + if ( '<' == decodeHelper.decode(s, 0) ) { + decodeHelper.decode(s, decodeHelper.next); + if ( '%' == decodeHelper.ch || '?' == decodeHelper.ch ) { + endScriptTag = decodeHelper.ch; + tokensOut.push(new PR_Token(s.substring(0, decodeHelper.next), + PR_TAG)); + s = s.substring(decodeHelper.next, s.length); + } + } + } + else if ( PR_TAG == tok.style ) { + if ( '<' == decodeHelper.decode(s, 0) && + '/' != s.charAt(decodeHelper.next) ) { + var tagContent = s.substring(decodeHelper.next).toLowerCase(); + // FIXME(msamuel): this does not mirror exactly the code in + // in PR_splitMarkup that defers splitting tags inside script and + // style blocks. + if ( PR_startsWith(tagContent, 'script') || + PR_startsWith(tagContent, 'style') || + PR_startsWith(tagContent, 'xmp') ) { + endScriptTag = '/'; + } + } + } + } + + if ( null != endScriptTag ) { + var endTok = null; + if ( PR_SOURCE == tok.style ) { + if ( endScriptTag == '%' || endScriptTag == '?' ) { + var pos = s.lastIndexOf(endScriptTag); + if ( pos >= 0 && '>' == decodeHelper.decode(s, pos + 1) && + s.length == decodeHelper.next ) { + endTok = new PR_Token(s.substring(pos, s.length), PR_TAG); + s = s.substring(0, pos); + } + } + if ( null == sourceChunks ) { + sourceChunks = []; + } + sourceChunks.push(new PR_Token(s, PR_PLAIN)); + } + else if ( PR_PLAIN == tok.style ) { + if ( null == sourceChunks ) { + sourceChunks = []; + } + sourceChunks.push(tok); + } + else if ( PR_TAG == tok.style ) { + // if it starts with </ then it must be the end tag. + if ( '<' == decodeHelper.decode(tok.token, 0) && + tok.token.length > decodeHelper.next && + '/' == decodeHelper.decode(tok.token, decodeHelper.next) ) { + endTok = tok; + } + else { + tokensOut.push(tok); + } + } + else if ( ci >= nc ) { + // force the token to close + endTok = tok; + } + else { + if ( sourceChunks ) { + sourceChunks.push(tok); + } + else { + // push remaining tag and attribute tokens from the opening tag + tokensOut.push(tok); + } + } + if ( endTok ) { + if ( sourceChunks ) { + var sourceTokens = PR_lexSource(sourceChunks); + tokensOut.push(new PR_Token('<span class=embsrc>', null)); + for ( var si = 0, ns = sourceTokens.length; si < ns; ++si ) { + tokensOut.push(sourceTokens[si]); + } + tokensOut.push(new PR_Token('</span>', null)); + sourceChunks = null; + } + if ( endTok.token ) { + tokensOut.push(endTok); + } + endScriptTag = null; + } + } + else { + tokensOut.push(tok); + } + } + return tokensOut; +} + +/** splits the quotes from an attribute value. + * ['"foo"'] -> ['"', 'foo', '"'] + * @private + */ +function PR_splitAttributeQuotes( tokens ) { + var firstPlain = null, lastPlain = null; + for ( var i = 0; i < tokens.length; ++i ) { + if ( PR_PLAIN == tokens[i].style ) { + firstPlain = i; + break; + } + } + for ( var i = tokens.length; --i >= 0; ) { + if ( PR_PLAIN == tokens[i].style ) { + lastPlain = i; + break; + } + } + if ( null == firstPlain ) { + return tokens; + } + + var decodeHelper = new PR_DecodeHelper(); + var fs = tokens[firstPlain].token; + var fc = decodeHelper.decode(fs, 0); + if ( '"' != fc && '\'' != fc ) { + return tokens; + } + var fpos = decodeHelper.next; + + var ls = tokens[lastPlain].token; + var lpos = ls.lastIndexOf('&'); + if ( lpos < 0 ) { + lpos = ls.length - 1; + } + var lc = decodeHelper.decode(ls, lpos); + if ( lc != fc || decodeHelper.next != ls.length ) { + lc = null; + lpos = ls.length; + } + + var tokensOut = []; + for ( var i = 0; i < firstPlain; ++i ) { + tokensOut.push(tokens[i]); + } + tokensOut.push(new PR_Token(fs.substring(0, fpos), PR_ATTRIB_VALUE)); + if ( lastPlain == firstPlain ) { + tokensOut.push(new PR_Token(fs.substring(fpos, lpos), PR_PLAIN)); + } + else { + tokensOut.push(new PR_Token(fs.substring(fpos, fs.length), PR_PLAIN)); + for ( var i = firstPlain + 1; i < lastPlain; ++i ) { + tokensOut.push(tokens[i]); + } + if ( lc ) { + tokens.push(new PR_Token(ls.substring(0, lpos), PR_PLAIN)); + } + else { + tokens.push(tokens[lastPlain]); + } + } + if ( lc ) { + tokensOut.push(new PR_Token(ls.substring(lpos, ls.length), PR_PLAIN)); + } + for ( var i = lastPlain + 1; i < tokens.length; ++i ) { + tokensOut.push(tokens[i]); + } + return tokensOut; +} + +/** identify attribute values that really contain source code and recursively + * lex them. + * @private + */ +function PR_splitSourceAttributes( tokens ) { + var tokensOut = []; + + var sourceChunks = null; + var inSource = false; + var name = ''; + + for ( var ci = 0, nc = tokens.length; ci < nc; ++ci ) { + var tok = tokens[ci]; + var outList = tokensOut; + if ( PR_TAG == tok.style ) { + if ( inSource ) { + inSource = false; + name = ''; + if ( sourceChunks ) { + tokensOut.push(new PR_Token('<span class=embsrc>', null)); + var sourceTokens = + PR_lexSource(PR_splitAttributeQuotes(sourceChunks)); + for ( var si = 0, ns = sourceTokens.length; si < ns; ++si ) { + tokensOut.push(sourceTokens[si]); + } + tokensOut.push(new PR_Token('</span>', null)); + sourceChunks = null; + } + } + else if ( name && tok.token.indexOf('=') >= 0 ) { + var nameLower = name.toLowerCase(); + if ( PR_startsWith(nameLower, 'on') || 'style' == nameLower ) { + inSource = true; + } + } + else { + name = ''; + } + } + else if ( PR_ATTRIB_NAME == tok.style ) { + name += tok.token; + } + else if ( PR_ATTRIB_VALUE == tok.style ) { + if ( inSource ) { + if ( null == sourceChunks ) { + sourceChunks = []; + } + outList = sourceChunks; + tok = new PR_Token(tok.token, PR_PLAIN); + } + } + else { + if ( sourceChunks ) { + outList = sourceChunks; + } + } + outList.push(tok); + } + return tokensOut; +} + +/** returns a list of PR_Token objects given chunks of source code. + * + * This code treats ", ', and ` as string delimiters, and \ as a string escape. + * It does not recognize perl's qq() style strings. It has no special handling + * for double delimiter escapes as in basic, or tje tripled delimiters used in + * python, but should work on those regardless although in those cases a single + * string literal may be broken up into multiple adjacent string literals. + * + * It recognizes C, C++, and shell style comments. + * + * @param chunks PR_Tokens with style in (null, PR_PLAIN) + */ +function PR_lexSource( chunks ) { + // split into strings, comments, and other. + // We do this because strings and comments are easily recognizable and can + // contain stuff that looks like other tokens, so we want to mark those early + // so we don't recurse into them. + var tokens = PR_splitStringAndCommentTokens(chunks); + + // split non comment|string tokens on whitespace and word boundaries + var tokensOut = []; + for ( var i = 0; i < tokens.length; ++i ) { + var tok = tokens[i]; + if ( PR_PLAIN === tok.style ) { + PR_splitNonStringNonCommentToken(tok.token, tokensOut); + continue; + } + tokensOut.push(tok); + } + + return tokensOut; +} + +/** returns a list of PR_Token objects given a string of markup. + * + * This code assumes that < tokens are html escaped, but " are not. + * It will do a resonable job with <, but will not recognize an " + * as starting a string. + * + * This code recognizes a number of constructs. + * <!-- ... --> comment + * <!\w ... > declaration + * <\w ... > tag + * </\w ... > tag + * <?...?> embedded source + * &[#\w]...; entity + * + * It does not recognizes %foo; entities. + * + * It will recurse into any <style>, <script>, and on* attributes using + * PR_lexSource. + */ +function PR_lexMarkup( chunks ) { + // This function works as follows: + // 1) Start by splitting the markup into text and tag chunks + // Input: String s + // Output: List<PR_Token> where style in (PR_PLAIN, null) + // 2) Then split the text chunks further into comments, declarations, + // tags, etc. + // After each split, consider whether the token is the start of an + // embedded source section, i.e. is an open <script> tag. If it is, + // find the corresponding close token, and don't bother to lex in between. + // Input: List<String> + // Output: List<PR_Token> with style in (PR_TAG, PR_PLAIN, PR_SOURCE, null) + // 3) Finally go over each tag token and split out attribute names and values. + // Input: List<PR_Token> + // Output: List<PR_Token> where style in + // (PR_TAG, PR_PLAIN, PR_SOURCE, NAME, VALUE, null) + var tokensOut = PR_tokenizeMarkup(chunks); + tokensOut = PR_splitTagAttributes(tokensOut); + tokensOut = PR_splitSourceNodes(tokensOut); + tokensOut = PR_splitSourceAttributes(tokensOut); + return tokensOut; +} + +/** + * classify the string as either source or markup and lex appropriately. + * @param {String} html + */ +function PR_lexOne( html ) { + var chunks = PR_expandTabs(PR_chunkify(html), PR_TAB_WIDTH); + + // treat it as markup if the first non whitespace character is a < and the + // last non-whitespace character is a > + var isMarkup = false; + for ( var i = 0; i < chunks.length; ++i ) { + if ( PR_PLAIN == chunks[i].style ) { + if ( PR_startsWith(PR_trim(chunks[i].token), '<') ) { + for ( var j = chunks.length; --j >= 0; ) { + if ( PR_PLAIN == chunks[j].style ) { + isMarkup = PR_endsWith(PR_trim(chunks[j].token), '>'); + break; + } + } + } + break; + } + } + + return isMarkup ? PR_lexMarkup(chunks) : PR_lexSource(chunks); +} + +/** pretty print a chunk of code. + * + * @param s code as html + * @return code as html, but prettier + */ +function prettyPrintOne( s ) { + try { + var tokens = PR_lexOne(s); + var out = []; + var lastStyle = null; + for ( var i = 0; i < tokens.length; i++ ) { + var t = tokens[i]; + if ( t.style != lastStyle ) { + if ( lastStyle != null ) { + out.push('</span>'); + } + if ( t.style != null ) { + out.push('<span class=', t.style, '>'); + } + lastStyle = t.style; + } + var html = t.token; + if ( null != t.style ) { + // This interacts badly with some wikis which introduces paragraph tags + // into pre blocks for some strange reason. + // It's necessary for IE though which seems to lose the preformattedness + // of <pre> tags when their innerHTML is assigned. + // http://stud3.tuwien.ac.at/~e0226430/innerHtmlQuirk.html + html = html + .replace(/(\r\n?|\n| ) /g, '$1 ') + .replace(/\r\n?|\n/g, '<br>'); + } + out.push(html); + } + if ( lastStyle != null ) { + out.push('</span>'); + } + return out.join(''); + } + catch ( e ) { + if ( 'console' in window ) { + console.log(e); + console.trace(); + } + return s; + } +} + +/** find all the < pre > and < code > tags in the DOM with class=prettyprint and + * prettify them. + */ +function prettyPrint() { + // fetch a list of nodes to rewrite + var codeSegments = [ + document.getElementsByTagName('pre'), + document.getElementsByTagName('code'), + document.getElementsByTagName('xmp') ]; + var elements = []; + for ( var i = 0; i < codeSegments.length; ++i ) { + for ( var j = 0; j < codeSegments[i].length; ++j ) { + elements.push(codeSegments[i][j]); + } + } + codeSegments = null; + + // the loop is broken into a series of continuations to make sure that we + // don't make the browser unresponsive when rewriting a large page. + var k = 0; + + function doWork() { + var endTime = new Date().getTime() + 250; + for ( ; k < elements.length && new Date().getTime() < endTime; k++ ) { + var cs = elements[k]; + if ( cs.className && cs.className.indexOf('prettyprint') >= 0 ) { + + // make sure this is not nested in an already prettified element + var nested = false; + for ( var p = cs.parentNode; p != null; p = p.parentNode ) { + if ( (p.tagName == 'pre' || p.tagName == 'code' || + p.tagName == 'xmp') && + p.className && p.className.indexOf('prettyprint') >= 0 ) { + nested = true; + break; + } + } + if ( !nested ) { + // fetch the content as a snippet of properly escaped HTML. + // Firefox adds newlines at the end. + var content = PR_getInnerHtml(cs); + content = content.replace(/(?:\r\n?|\n)$/, ''); + + // do the pretty printing + var newContent = prettyPrintOne(content); + + // push the prettified html back into the tag. + if ( !PR_isRawContent(cs) ) { + // just replace the old html with the new + cs.innerHTML = newContent; + } + else { + // we need to change the tag to a <pre> since <xmp>s do not allow + // embedded tags such as the span tags used to attach styles to + // sections of source code. + var pre = document.createElement('PRE'); + for ( var i = 0; i < cs.attributes.length; ++i ) { + var a = cs.attributes[i]; + if ( a.specified ) { + pre.setAttribute(a.name, a.value); + } + } + pre.innerHTML = newContent; + // remove the old + cs.parentNode.replaceChild(pre, cs); + } + } + } + } + if ( k < elements.length ) { + // finish up in a continuation + setTimeout(doWork, 250); + } + } + + doWork(); +} diff --git a/third_party/java/jopt-simple/src/site/site.xml b/third_party/java/jopt-simple/src/site/site.xml new file mode 100644 index 0000000000..8dafe09e18 --- /dev/null +++ b/third_party/java/jopt-simple/src/site/site.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project name="JOpt Simple - a Java command line parsing library"> + <bannerLeft> + <name>JOpt Simple</name> + <src>images/jopt-simple-logo.png</src> + <href>http://pholser.github.com/jopt-simple/</href> + </bannerLeft> + <body> + <menu name="JOpt Simple"> + <item name="Overview" href="index.html"/> + <item name="Download" href="download.html"/> + <item name="Examples" href="examples.html"/> + <item name="Change Log" href="changes.html"/> + <item name="Javadoc" href="apidocs/index.html"/> + <item name="Developer Docs" href="developer.html"/> + <item name="Acknowledgements" href="acknowledgments.html"/> + </menu> + <menu ref="reports"/> + </body> +</project> diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/AbstractOptionParserFixture.java b/third_party/java/jopt-simple/src/test/java/joptsimple/AbstractOptionParserFixture.java new file mode 100644 index 0000000000..3385c51249 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/AbstractOptionParserFixture.java @@ -0,0 +1,59 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.rules.ExpectedException; + +import static org.junit.Assert.*; +import static org.junit.rules.ExpectedException.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public abstract class AbstractOptionParserFixture { + @Rule public final ExpectedException thrown = none(); + + protected OptionParser parser; + + @Before + public final void createNewParser() { + parser = new OptionParser(); + } + + static void assertOptionDetected( OptionSet detectedOptions, String option ) { + assertTrue( "option '" + option + "' not detected?", detectedOptions.has( option ) ); + } + + static void assertOptionNotDetected( OptionSet detectedOptions, String option ) { + assertOptionNotDetected( "option '" + option + "' detected?", detectedOptions, option ); + } + + static void assertOptionNotDetected( String message, OptionSet detectedOptions, String option ) { + assertFalse( message, detectedOptions.has( option ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/AbstractOptionSpecFixture.java b/third_party/java/jopt-simple/src/test/java/joptsimple/AbstractOptionSpecFixture.java new file mode 100644 index 0000000000..91901c9bd4 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/AbstractOptionSpecFixture.java @@ -0,0 +1,58 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import org.infinitest.toolkit.EqualsHashCodeTestSupport; +import org.junit.Test; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public abstract class AbstractOptionSpecFixture extends EqualsHashCodeTestSupport { + @Override + protected AbstractOptionSpec<?> equal() { + return createEqualOptionSpecInstance(); + } + + @Override + protected AbstractOptionSpec<?> notEqual() { + return createNotEqualOptionSpecInstance(); + } + + protected abstract AbstractOptionSpec<?> createEqualOptionSpecInstance(); + + protected abstract AbstractOptionSpec<?> createNotEqualOptionSpecInstance(); + + @Test( expected = NullPointerException.class ) + public final void testValuesWithNullOptionSet() { + createEqualOptionSpecInstance().values( null ); + } + + @Test( expected = NullPointerException.class ) + public final void testValueWithNullOptionSet() { + createNotEqualOptionSpecInstance().value( null ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/AbstractOptionSpecOptionsImmutabilityTestCase.java b/third_party/java/jopt-simple/src/test/java/joptsimple/AbstractOptionSpecOptionsImmutabilityTestCase.java new file mode 100644 index 0000000000..0660640efa --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/AbstractOptionSpecOptionsImmutabilityTestCase.java @@ -0,0 +1,53 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.List; + +import org.infinitest.toolkit.UnmodifiableListTestSupport; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public abstract class AbstractOptionSpecOptionsImmutabilityTestCase extends UnmodifiableListTestSupport<String> { + @Override + protected List<String> newList() { + AbstractOptionSpec<?> spec = newOptionSpec( containedItem() ); + return spec.options(); + } + + @Override + protected final String newItem() { + return "not"; + } + + @Override + protected String containedItem() { + return "in"; + } + + protected abstract AbstractOptionSpec<?> newOptionSpec( String option ); +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/AbstractOptionSpecValuesImmutabilityTestCase.java b/third_party/java/jopt-simple/src/test/java/joptsimple/AbstractOptionSpecValuesImmutabilityTestCase.java new file mode 100644 index 0000000000..9e41ef8fc3 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/AbstractOptionSpecValuesImmutabilityTestCase.java @@ -0,0 +1,52 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.Collections; +import java.util.List; + +import org.infinitest.toolkit.UnmodifiableListTestSupport; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public abstract class AbstractOptionSpecValuesImmutabilityTestCase<T> extends UnmodifiableListTestSupport<T> { + @Override + protected List<T> newList() { + AbstractOptionSpec<T> spec = newOptionSpec(); + OptionSet options = new OptionSet( Collections.<String, AbstractOptionSpec<?>> emptyMap() ); + options.addWithArgument( spec, firstArg() ); + options.addWithArgument( spec, secondArg() ); + + return spec.values( options ); + } + + protected abstract AbstractOptionSpec<T> newOptionSpec(); + + protected abstract String firstArg(); + + protected abstract String secondArg(); +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/AlternativeLongOptionSpecOptionsImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/AlternativeLongOptionSpecOptionsImmutabilityTest.java new file mode 100644 index 0000000000..529557d6ab --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/AlternativeLongOptionSpecOptionsImmutabilityTest.java @@ -0,0 +1,43 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static joptsimple.ParserRules.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class AlternativeLongOptionSpecOptionsImmutabilityTest extends AbstractOptionSpecOptionsImmutabilityTestCase { + @Override + protected AbstractOptionSpec<?> newOptionSpec( String option ) { + return new AlternativeLongOptionSpec(); + } + + @Override + protected String containedItem() { + return RESERVED_FOR_EXTENSIONS; + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/AlternativeLongOptionSpecValuesImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/AlternativeLongOptionSpecValuesImmutabilityTest.java new file mode 100644 index 0000000000..933c171865 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/AlternativeLongOptionSpecValuesImmutabilityTest.java @@ -0,0 +1,58 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class AlternativeLongOptionSpecValuesImmutabilityTest + extends AbstractOptionSpecValuesImmutabilityTestCase<String> { + + @Override + protected AbstractOptionSpec<String> newOptionSpec() { + return new AlternativeLongOptionSpec(); + } + + @Override + protected String firstArg() { + return "x=y"; + } + + @Override + protected String secondArg() { + return "z=w"; + } + + @Override + protected String newItem() { + return "a=b"; + } + + @Override + protected String containedItem() { + return "x=y"; + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ArgumentAcceptingOptionSpecDefaultValuesImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ArgumentAcceptingOptionSpecDefaultValuesImmutabilityTest.java new file mode 100644 index 0000000000..d20c48cb9f --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ArgumentAcceptingOptionSpecDefaultValuesImmutabilityTest.java @@ -0,0 +1,50 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.List; + +import org.infinitest.toolkit.UnmodifiableListTestSupport; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class ArgumentAcceptingOptionSpecDefaultValuesImmutabilityTest extends UnmodifiableListTestSupport<String> { + @Override + protected List<String> newList() { + return new RequiredArgumentOptionSpec<String>( "option" ).defaultsTo( "a", "b" ).defaultValues(); + } + + @Override + protected String containedItem() { + return "a"; + } + + @Override + protected String newItem() { + return "c"; + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ArgumentAcceptingOptionSpecTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ArgumentAcceptingOptionSpecTest.java new file mode 100644 index 0000000000..32ef589fec --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ArgumentAcceptingOptionSpecTest.java @@ -0,0 +1,136 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import org.infinitest.toolkit.Block; +import org.junit.Test; + +import static org.infinitest.toolkit.Assertions.*; +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class ArgumentAcceptingOptionSpecTest { + @Test( expected = NullPointerException.class ) + public void requiredArgOfNullType() { + new RequiredArgumentOptionSpec<Void>( "a" ).ofType( null ); + } + + @Test( expected = NullPointerException.class ) + public void optionalArgOfNullType() { + new OptionalArgumentOptionSpec<Void>( "verbose" ).ofType( null ); + } + + @Test( expected = IllegalArgumentException.class ) + public void requiredArgOfNonValueType() { + new RequiredArgumentOptionSpec<Void>( "threshold" ).ofType( Object.class ); + } + + @Test( expected = IllegalArgumentException.class ) + public void optionalArgOfNonValueType() { + new OptionalArgumentOptionSpec<Void>( "max" ).ofType( Object.class ); + } + + @Test + public void requiredArgOfValueTypeBasedOnValueOf() { + assertNoException( new Block() { + public void execute() { + new RequiredArgumentOptionSpec<Void>( "threshold" ).ofType( ValueOfHaver.class ); + } + } ); + } + + @Test + public void optionalArgOfValueTypeBasedOnValueOf() { + assertNoException( new Block() { + public void execute() { + new OptionalArgumentOptionSpec<Void>( "abc" ).ofType( ValueOfHaver.class ); + } + } ); + } + + @Test + public void requiredArgOfValueTypeBasedOnCtor() { + assertNoException( new Block() { + public void execute() { + new RequiredArgumentOptionSpec<Void>( "threshold" ).ofType( Ctor.class ); + } + } ); + } + + @Test + public void optionalArgOfValueTypeBasedOnCtor() { + final OptionalArgumentOptionSpec<Ctor> spec = new OptionalArgumentOptionSpec<>( "abc" ); + + assertNoException( new Block() { + public void execute() { + spec.ofType( Ctor.class ); + assertEquals( "foo", spec.convert( "foo" ).getS() ); + } + } ); + } + + @Test( expected = IllegalArgumentException.class ) + public void rejectsUnicodeZeroAsCharValueSeparatorForRequiredArgument() { + new RequiredArgumentOptionSpec<Void>( "a" ).withValuesSeparatedBy( '\u0000' ); + } + + @Test( expected = IllegalArgumentException.class ) + public void rejectsUnicodeZeroAsCharValueSeparatorForOptionalArgument() { + new OptionalArgumentOptionSpec<Void>( "b" ).withValuesSeparatedBy( '\u0000' ); + } + + @Test( expected = IllegalArgumentException.class ) + public void rejectsUnicodeZeroInStringValueSeparatorForRequiredArgument() { + new RequiredArgumentOptionSpec<Void>( "c" ).withValuesSeparatedBy( "::\u0000::" ); + } + + @Test( expected = IllegalArgumentException.class ) + public void rejectsUnicodeZeroInStringValueSeparatorForOptionalArgument() { + new OptionalArgumentOptionSpec<Void>( "d" ).withValuesSeparatedBy( "::::\u0000" ); + } + + @Test( expected = NullPointerException.class ) + public void rejectsNullConverter() { + new RequiredArgumentOptionSpec<Void>( "c" ).withValuesConvertedBy( null ); + } + + @Test( expected = NullPointerException.class ) + public void rejectsNullDefaultValue() { + new RequiredArgumentOptionSpec<Integer>( "d" ).defaultsTo( null ); + } + + @Test( expected = NullPointerException.class ) + public void rejectsNullDefaultValueRemainder() { + new RequiredArgumentOptionSpec<Integer>( "d" ).defaultsTo( 2, (Integer[]) null ); + } + + @Test( expected = NullPointerException.class ) + public void rejectsNullInDefaultValueRemainder() { + new RequiredArgumentOptionSpec<Integer>( "d" ).defaultsTo( 2, 3, null ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ArgumentListHasNoMoreArgsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ArgumentListHasNoMoreArgsTest.java new file mode 100644 index 0000000000..1ae50755cd --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ArgumentListHasNoMoreArgsTest.java @@ -0,0 +1,56 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import org.junit.Before; +import org.junit.Test; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class ArgumentListHasNoMoreArgsTest { + private ArgumentList noMore; + + @Before + public void setUp() { + noMore = new ArgumentList(); + } + + @Test( expected = IndexOutOfBoundsException.class ) + public void peek() { + noMore.peek(); + } + + @Test( expected = IndexOutOfBoundsException.class ) + public void next() { + noMore.next(); + } + + @Test( expected = IndexOutOfBoundsException.class ) + public void treatNextAsLongOption() { + noMore.treatNextAsLongOption(); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ArgumentListTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ArgumentListTest.java new file mode 100644 index 0000000000..425a41a97d --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ArgumentListTest.java @@ -0,0 +1,75 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class ArgumentListTest { + private ArgumentList args; + + @Before + public void setUp() { + args = new ArgumentList( "-a", "b", "c" ); + } + + @Test + public void nextAndPeek() { + assertNextArgumentIs( "-a" ); + assertNextArgumentIs( "b" ); + assertNextArgumentIs( "c" ); + assertNoMoreArguments(); + } + + @Test + public void treatNextAsLongOption() { + args.treatNextAsLongOption(); + assertNextArgumentIs( "-a" ); + + args.treatNextAsLongOption(); + assertNextArgumentIs( "--b" ); + + args.treatNextAsLongOption(); + assertNextArgumentIs( "--c" ); + + assertNoMoreArguments(); + } + + private void assertNextArgumentIs( String expectedArg ) { + assertTrue( "no more arguments?", args.hasMore() ); + assertEquals( "peek?", expectedArg, args.peek() ); + assertEquals( "next?", expectedArg, args.next() ); + } + + private void assertNoMoreArguments() { + assertFalse( "more arguments?", args.hasMore() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/AvailableIfAnyTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/AvailableIfAnyTest.java new file mode 100644 index 0000000000..c3e4e592f6 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/AvailableIfAnyTest.java @@ -0,0 +1,82 @@ +/* + The MIT License + + Copyright (c) 2004-2014 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import org.junit.Before; +import org.junit.Test; + +import static java.util.Collections.emptyList; + +import static org.junit.Assert.assertEquals; + +public class AvailableIfAnyTest extends AbstractOptionParserFixture { + @Before + public void configureParser() { + OptionSpec<Void> a = parser.accepts( "a" ); + parser.accepts( "b" ); + OptionSpec<Void> c = parser.accepts( "c" ); + parser.accepts( "d" ); + parser.accepts( "n" ).availableIf( a, c ); + } + + @Test + public void rejectsCommandLineExistingForbiddenOption() { + thrown.expect( UnavailableOptionException.class ); + + parser.parse( "-b", "-n" ); + } + + @Test + public void rejectsCommandLineExistingOtherForbiddenOption() { + thrown.expect( UnavailableOptionException.class ); + + parser.parse( "-d", "-n" ); + } + + @Test + public void rejectsCommandLineOnlyForbiddenOption() { + thrown.expect( UnavailableOptionException.class ); + + parser.parse( "-n" ); + } + + @Test + public void rejectsCommandLineWithNotAllConditionallyRequiredOptionsPresent() { + thrown.expect( UnavailableOptionException.class ); + + parser.parse( "-b", "-d", "-n" ); + } + + @Test + public void acceptsCommandLineWithAllowedOptionsPresent() { + OptionSet options = parser.parse( "-a", "-c", "-n" ); + + assertOptionDetected( options, "a" ); + assertOptionDetected( options, "c" ); + assertOptionDetected( options, "n" ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/AvailableIfUnlessTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/AvailableIfUnlessTest.java new file mode 100644 index 0000000000..6f394b8311 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/AvailableIfUnlessTest.java @@ -0,0 +1,143 @@ +/* + The MIT License + + Copyright (c) 2004-2014 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import org.junit.Before; +import org.junit.Test; + +import static java.util.Arrays.asList; +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; + +import static org.junit.Assert.assertEquals; + +public class AvailableIfUnlessTest extends AbstractOptionParserFixture { + @Before + public void configureParser() { + parser.mutuallyExclusive( + parser.acceptsAll( asList( "ftp", "file-transfer" ) ), + parser.accepts( "file" ), + parser.accepts( "http" ) + ); + + parser.acceptsAll( asList( "username", "userid" ) ).availableIf( "file-transfer" ).withRequiredArg(); + parser.acceptsAll( asList( "password", "pwd" ) ).availableIf( "ftp" ).withRequiredArg(); + parser.acceptsAll( asList( "directory", "dir" ) ).availableIf( "file" ).withRequiredArg(); + parser.accepts( "?" ).forHelp(); + } + + @Test + public void rejectsEmptyMutualExclusiveness() { + thrown.expect( NullPointerException.class ); + + parser.mutuallyExclusive( (OptionSpecBuilder[]) null ); + } + + @Test + public void rejectsConflictingCommandLineOptions1() { + thrown.expect( UnavailableOptionException.class ); + + parser.parse( "--ftp", "--file" ); + } + + @Test + public void rejectsConflictingCommandLineOptions2() { + thrown.expect( UnavailableOptionException.class ); + + parser.parse( "--ftp", "--http" ); + } + + @Test + public void rejectsIncompatibleOptions1() { + thrown.expect( UnavailableOptionException.class ); + + parser.parse( "--file", "--username", "joe" ); + } + + @Test + public void rejectsIncompatibleOptions2() { + thrown.expect( UnavailableOptionException.class ); + + parser.parse( "--ftp", "--directory", "/tmp" ); + } + + + @Test + public void acceptsCommandLineWithConditionallyAllowedOptionsPresent1() { + OptionSet options = parser.parse( "--ftp", "--userid", "joe", "--password=secret" ); + + assertOptionDetected( options, "ftp" ); + assertOptionDetected( options, "username" ); + assertOptionDetected( options, "password" ); + assertEquals( singletonList( "joe" ), options.valuesOf( "username" ) ); + assertEquals( singletonList( "secret" ), options.valuesOf( "password" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void acceptsCommandLineWithConditionallyAllowedOptionsPresent2() { + OptionSet options = parser.parse( "--file", "--dir", "/tmp"); + + assertOptionDetected( options, "file" ); + assertOptionDetected( options, "dir" ); + assertEquals( singletonList( "/tmp" ), options.valuesOf( "dir" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void rejectsCommandLineOnlyContainingForbiddenOptionSynonym() { + thrown.expect( UnavailableOptionException.class ); + + parser.parse( "--pwd", "secret" ); + } + + @Test + public void rejectsOptionNotAlreadyConfigured() { + thrown.expect( UnconfiguredOptionException.class ); + + parser.accepts( "foo" ).availableIf( "bar" ); + parser.accepts( "foo" ).availableUnless( "bar" ); + } + + @Test + public void presenceOfHelpOptionNegatesAllowedIfness() { + OptionSet options = parser.parse( "--file", "--userid", "joe", "-?" ); + + assertOptionDetected( options, "file" ); + assertOptionDetected( options, "?" ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void presenceOfHelpOptionNegatesAllowedUnlessness() { + OptionSet options = parser.parse( "--file", "--ftp", "-?" ); + + assertOptionDetected( options, "file" ); + assertOptionDetected( options, "file-transfer" ); + assertOptionDetected( options, "?" ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/AvailableUnlessAnyTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/AvailableUnlessAnyTest.java new file mode 100644 index 0000000000..c55191654b --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/AvailableUnlessAnyTest.java @@ -0,0 +1,82 @@ +/* + The MIT License + + Copyright (c) 2004-2014 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import org.junit.Before; +import org.junit.Test; + +import static java.util.Collections.emptyList; + +import static org.junit.Assert.assertEquals; + +public class AvailableUnlessAnyTest extends AbstractOptionParserFixture { + @Before + public void configureParser() { + parser.accepts( "a" ); + parser.accepts( "b" ); + OptionSpec<Void> c = parser.accepts( "c" ); + parser.accepts( "d" ); + parser.accepts( "n" ).availableUnless( "a" ).availableUnless( c ); + } + + @Test + public void rejectsCommandLineExistingForbiddenOption() { + thrown.expect( UnavailableOptionException.class ); + + parser.parse( "-a", "-n" ); + } + + @Test + public void rejectsCommandLineExistingOtherForbiddenOption() { + thrown.expect( UnavailableOptionException.class ); + + parser.parse( "-c", "-n" ); + } + + @Test + public void rejectsCommandLineOnlyForbiddenOption() { + OptionSet options = parser.parse( "-n" ); + + assertOptionDetected( options, "n" ); + } + + @Test + public void rejectsCommandLineWithNotAllConditionallyRequiredOptionsPresent() { + thrown.expect( UnavailableOptionException.class ); + + parser.parse( "-a", "-c", "-n" ); + } + + @Test + public void acceptsCommandLineWithAllowedOptionsPresent() { + OptionSet options = parser.parse( "-d", "-b", "-n" ); + + assertOptionDetected( options, "b" ); + assertOptionDetected( options, "d" ); + assertOptionDetected( options, "n" ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ClusterVersusLongOptionTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ClusterVersusLongOptionTest.java new file mode 100644 index 0000000000..be71a1eb2c --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ClusterVersusLongOptionTest.java @@ -0,0 +1,84 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class ClusterVersusLongOptionTest extends AbstractOptionParserFixture { + @Before + public final void initializeParser() { + parser.accepts( "fox" ); + parser.accepts( "f" ); + parser.accepts( "o" ); + parser.accepts( "x" ); + } + + @Test + public void resolvesToLongOptionEvenWithMatchingShortOptions() { + OptionSet options = parser.parse( "--fox" ); + assertTrue( options.has( "fox" ) ); + assertFalse( options.has( "f" ) ); + assertFalse( options.has( "o" ) ); + assertFalse( options.has( "x" ) ); + } + + @Test + public void resolvesToLongOptionWithSingleDashEvenWithMatchingShortOptions() { + OptionSet options = parser.parse( "-fox" ); + assertTrue( options.has( "fox" ) ); + assertFalse( options.has( "f" ) ); + assertFalse( options.has( "o" ) ); + assertFalse( options.has( "x" ) ); + } + + @Test + public void resolvesAbbreviationToLongOption() { + OptionSet options = parser.parse( "-fo" ); + assertTrue( options.has( "fox" ) ); + assertFalse( options.has( "f" ) ); + assertFalse( options.has( "o" ) ); + } + + @Test + public void resolvesShortOptionToShortOption() { + OptionSet options = parser.parse( "-f" ); + assertFalse( options.has( "fox" ) ); + assertTrue( options.has( "f" ) ); + } + + @Test + public void resolvesShortOptionToShortOptionEvenWithDoubleHyphen() { + OptionSet options = parser.parse( "--f" ); + assertFalse( options.has( "fox" ) ); + assertTrue( options.has( "f" ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ClusterVersusLongOptionWithOptionalArgumentTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ClusterVersusLongOptionWithOptionalArgumentTest.java new file mode 100644 index 0000000000..4e917648bb --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ClusterVersusLongOptionWithOptionalArgumentTest.java @@ -0,0 +1,122 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Collections.*; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class ClusterVersusLongOptionWithOptionalArgumentTest extends AbstractOptionParserFixture { + @Before + public final void initializeParser() { + parser.accepts( "fox" ); + parser.accepts( "f" ); + parser.accepts( "o" ); + parser.accepts( "x" ).withOptionalArg(); + } + + @Test + public void resolvesToLongOptionEvenWithMatchingShortOptions() { + OptionSet options = parser.parse( "--fox" ); + assertTrue( options.has( "fox" ) ); + assertFalse( options.has( "f" ) ); + assertFalse( options.has( "o" ) ); + assertFalse( options.has( "x" ) ); + } + + @Test + public void resolvesToLongOptionWithSingleDashEvenWithMatchingShortOptions() { + OptionSet options = parser.parse( "-fox" ); + assertTrue( options.has( "fox" ) ); + assertFalse( options.has( "f" ) ); + assertFalse( options.has( "o" ) ); + assertFalse( options.has( "x" ) ); + } + + @Test + public void resolvesAbbreviationToLongOption() { + OptionSet options = parser.parse( "-fo" ); + assertTrue( options.has( "fox" ) ); + assertFalse( options.has( "f" ) ); + assertFalse( options.has( "o" ) ); + } + + @Test + public void resolvesShortOptionToShortOption() { + OptionSet options = parser.parse( "-f" ); + assertFalse( options.has( "fox" ) ); + assertTrue( options.has( "f" ) ); + } + + @Test + public void resolvesShortOptionToShortOptionEvenWithDoubleHyphen() { + OptionSet options = parser.parse( "--f" ); + assertFalse( options.has( "fox" ) ); + assertTrue( options.has( "f" ) ); + } + + @Test + public void resolvesToShortOptionsWithArgumentFollowingX() { + OptionSet options = parser.parse( "-foxbar" ); + assertFalse( options.has( "fox" ) ); + assertTrue( options.has( "f" ) ); + assertTrue( options.has( "o" ) ); + assertTrue( options.has( "x" ) ); + assertEquals( singletonList( "bar" ), options.valuesOf( "x" ) ); + } + + @Test + public void shortOptionsInDifferentOrder() { + OptionSet options = parser.parse( "-fxo" ); + assertFalse( options.has( "fox" ) ); + assertTrue( options.has( "f" ) ); + assertFalse( options.has( "o" ) ); + assertTrue( options.has( "x" ) ); + assertEquals( singletonList( "o" ), options.valuesOf( "x" ) ); + } + + @Test( expected = UnrecognizedOptionException.class ) + public void longOptionWithMessedUpOrder() { + parser.parse( "--fxo" ); + } + + @Test + public void withArgumentComingAfterCluster() { + OptionSet options = parser.parse( "-fox", "bar" ); + + assertTrue( options.has( "fox" ) ); + assertFalse( options.has( "f" ) ); + assertFalse( options.has( "o" ) ); + assertFalse( options.has( "x" ) ); + assertEquals( singletonList( "bar" ), options.nonOptionArguments() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ClusterVersusLongOptionWithRequiredArgumentTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ClusterVersusLongOptionWithRequiredArgumentTest.java new file mode 100644 index 0000000000..b20fe67d92 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ClusterVersusLongOptionWithRequiredArgumentTest.java @@ -0,0 +1,122 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Collections.*; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class ClusterVersusLongOptionWithRequiredArgumentTest extends AbstractOptionParserFixture { + @Before + public final void initializeParser() { + parser.accepts( "fox" ); + parser.accepts( "f" ); + parser.accepts( "o" ); + parser.accepts( "x" ).withRequiredArg(); + } + + @Test + public void resolvesToLongOptionEvenWithMatchingShortOptions() { + OptionSet options = parser.parse( "--fox" ); + assertTrue( options.has( "fox" ) ); + assertFalse( options.has( "f" ) ); + assertFalse( options.has( "o" ) ); + assertFalse( options.has( "x" ) ); + } + + @Test + public void resolvesToLongOptionWithSingleDashEvenWithMatchingShortOptions() { + OptionSet options = parser.parse( "-fox" ); + assertTrue( options.has( "fox" ) ); + assertFalse( options.has( "f" ) ); + assertFalse( options.has( "o" ) ); + assertFalse( options.has( "x" ) ); + } + + @Test + public void resolvesAbbreviationToLongOption() { + OptionSet options = parser.parse( "-fo" ); + assertTrue( options.has( "fox" ) ); + assertFalse( options.has( "f" ) ); + assertFalse( options.has( "o" ) ); + } + + @Test + public void resolvesShortOptionToShortOption() { + OptionSet options = parser.parse( "-f" ); + assertFalse( options.has( "fox" ) ); + assertTrue( options.has( "f" ) ); + } + + @Test + public void resolvesShortOptionToShortOptionEvenWithDoubleHyphen() { + OptionSet options = parser.parse( "--f" ); + assertFalse( options.has( "fox" ) ); + assertTrue( options.has( "f" ) ); + } + + @Test + public void resolvesToShortOptionsWithArgumentFollowingX() { + OptionSet options = parser.parse( "-foxbar" ); + assertFalse( options.has( "fox" ) ); + assertTrue( options.has( "f" ) ); + assertTrue( options.has( "o" ) ); + assertTrue( options.has( "x" ) ); + assertEquals( singletonList( "bar" ), options.valuesOf( "x" ) ); + } + + @Test + public void shortOptionsInDifferentOrder() { + OptionSet options = parser.parse( "-fxo" ); + assertFalse( options.has( "fox" ) ); + assertTrue( options.has( "f" ) ); + assertFalse( options.has( "o" ) ); + assertTrue( options.has( "x" ) ); + assertEquals( singletonList( "o" ), options.valuesOf( "x" ) ); + } + + @Test( expected = UnrecognizedOptionException.class ) + public void longOptionWithMessedUpOrder() { + parser.parse( "--fxo" ); + } + + @Test + public void withArgumentComingAfterCluster() { + OptionSet options = parser.parse( "-fox", "bar" ); + + assertTrue( options.has( "fox" ) ); + assertFalse( options.has( "f" ) ); + assertFalse( options.has( "o" ) ); + assertFalse( options.has( "x" ) ); + assertEquals( singletonList( "bar" ), options.nonOptionArguments() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ClusterWhereManyOptionsAcceptArgumentsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ClusterWhereManyOptionsAcceptArgumentsTest.java new file mode 100644 index 0000000000..ae82f27662 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ClusterWhereManyOptionsAcceptArgumentsTest.java @@ -0,0 +1,183 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Collections.*; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class ClusterWhereManyOptionsAcceptArgumentsTest extends AbstractOptionParserFixture { + @Before + public final void initializeParser() { + parser.accepts( "f" ); + parser.accepts( "o" ).withOptionalArg(); + parser.accepts( "x" ).withRequiredArg(); + } + + @Test + public void foxPermutation() { + OptionSet options = parser.parse( "-fox" ); + + assertTrue( options.has( "f" ) ); + assertTrue( options.has( "o" ) ); + assertFalse( options.has( "x" ) ); + + assertEquals( singletonList( "x" ), options.valuesOf( "o" ) ); + } + + @Test + public void fxoPermutation() { + OptionSet options = parser.parse( "-fxo" ); + + assertTrue( options.has( "f" ) ); + assertFalse( options.has( "o" ) ); + assertTrue( options.has( "x" ) ); + + assertEquals( singletonList( "o" ), options.valuesOf( "x" ) ); + } + + @Test + public void ofxPermutation() { + OptionSet options = parser.parse( "-ofx" ); + + assertFalse( options.has( "f" ) ); + assertTrue( options.has( "o" ) ); + assertFalse( options.has( "x" ) ); + + assertEquals( singletonList( "fx" ), options.valuesOf( "o" ) ); + } + + @Test + public void oxfPermutation() { + OptionSet options = parser.parse( "-oxf" ); + + assertFalse( options.has( "f" ) ); + assertTrue( options.has( "o" ) ); + assertFalse( options.has( "x" ) ); + + assertEquals( singletonList( "xf" ), options.valuesOf( "o" ) ); + } + + @Test + public void xofPermutation() { + OptionSet options = parser.parse( "-xof" ); + + assertFalse( options.has( "f" ) ); + assertFalse( options.has( "o" ) ); + assertTrue( options.has( "x" ) ); + + assertEquals( singletonList( "of" ), options.valuesOf( "x" ) ); + } + + @Test + public void xfoPermutation() { + OptionSet options = parser.parse( "-xfo" ); + + assertFalse( options.has( "f" ) ); + assertFalse( options.has( "o" ) ); + assertTrue( options.has( "x" ) ); + + assertEquals( singletonList( "fo" ), options.valuesOf( "x" ) ); + } + + @Test + public void foxPermutationWithFollowingArg() { + OptionSet options = parser.parse( "-fox", "bar" ); + + assertTrue( options.has( "f" ) ); + assertTrue( options.has( "o" ) ); + assertFalse( options.has( "x" ) ); + + assertEquals( singletonList( "x" ), options.valuesOf( "o" ) ); + assertEquals( singletonList( "bar" ), options.nonOptionArguments() ); + } + + @Test + public void fxoPermutationWithFollowingArg() { + OptionSet options = parser.parse( "-fxo", "bar" ); + + assertTrue( options.has( "f" ) ); + assertFalse( options.has( "o" ) ); + assertTrue( options.has( "x" ) ); + + assertEquals( singletonList( "o" ), options.valuesOf( "x" ) ); + assertEquals( singletonList( "bar" ), options.nonOptionArguments() ); + } + + @Test + public void ofxPermutationWithFollowingArg() { + OptionSet options = parser.parse( "-ofx", "bar" ); + + assertFalse( options.has( "f" ) ); + assertTrue( options.has( "o" ) ); + assertFalse( options.has( "x" ) ); + + assertEquals( singletonList( "fx" ), options.valuesOf( "o" ) ); + assertEquals( singletonList( "bar" ), options.nonOptionArguments() ); + } + + @Test + public void oxfPermutationWithFollowingArg() { + OptionSet options = parser.parse( "-oxf", "bar" ); + + assertFalse( options.has( "f" ) ); + assertTrue( options.has( "o" ) ); + assertFalse( options.has( "x" ) ); + + assertEquals( singletonList( "xf" ), options.valuesOf( "o" ) ); + assertEquals( singletonList( "bar" ), options.nonOptionArguments() ); + } + + @Test + public void xofPermutationWithFollowingArg() { + OptionSet options = parser.parse( "-xof", "bar" ); + + assertFalse( options.has( "f" ) ); + assertFalse( options.has( "o" ) ); + assertTrue( options.has( "x" ) ); + + assertEquals( singletonList( "of" ), options.valuesOf( "x" ) ); + assertEquals( singletonList( "bar" ), options.nonOptionArguments() ); + } + + @Test + public void xfoPermutationWithFollowingArg() { + OptionSet options = parser.parse( "-xfo", "bar" ); + + assertFalse( options.has( "f" ) ); + assertFalse( options.has( "o" ) ); + assertTrue( options.has( "x" ) ); + + assertEquals( singletonList( "fo" ), options.valuesOf( "x" ) ); + assertEquals( singletonList( "bar" ), options.nonOptionArguments() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ConfigurableOptionParserHelpTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ConfigurableOptionParserHelpTest.java new file mode 100644 index 0000000000..066ca28a1d --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ConfigurableOptionParserHelpTest.java @@ -0,0 +1,484 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.io.StringWriter; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; + +import static java.math.BigDecimal.*; +import static java.util.Arrays.*; +import static java.util.Collections.*; + +import org.junit.Before; +import org.junit.Test; + +import static joptsimple.internal.Strings.*; +import static joptsimple.util.DateConverter.*; +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class ConfigurableOptionParserHelpTest extends AbstractOptionParserFixture { + private StringWriter sink; + + @Before + public final void createSink() { + parser.formatHelpWith( new BuiltinHelpFormatter( 120, 3 ) ); + sink = new StringWriter(); + } + + @Test + public void unconfiguredParser() throws Exception { + parser.printHelpOn( sink ); + + assertHelpLines( "No options specified ", EMPTY ); + } + + @Test + public void oneOptionNoArgNoDescription() throws Exception { + parser.accepts( "apple" ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description", + "------ -----------", + "--apple ", + EMPTY ); + } + + @Test + public void oneOptionNoArgWithDescription() throws Exception { + parser.accepts( "a", "some description" ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "-a some description", + EMPTY ); + } + + @Test + public void twoOptionsNoArgWithDescription() throws Exception { + parser.accepts( "a", "some description" ); + parser.accepts( "verbose", "even more description" ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "-a some description ", + "--verbose even more description", + EMPTY ); + } + + @Test + public void oneOptionRequiredArgNoDescription() throws Exception { + parser.accepts( "a" ).withRequiredArg(); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description", + "------ -----------", + "-a <String> ", + EMPTY ); + } + + @Test + public void oneOptionRequiredArgNoDescriptionWithType() throws Exception { + parser.accepts( "a" ).withRequiredArg().ofType( Integer.class ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description", + "------ -----------", + "-a <Integer> ", + EMPTY ); + } + + @Test + public void oneOptionRequiredArgWithDescription() throws Exception { + parser.accepts( "a", "some value you need" ).withRequiredArg().describedAs( "numerical" ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "-a <String: numerical> some value you need", + EMPTY ); + } + + @Test + public void oneOptionRequiredArgWithDescriptionAndType() throws Exception { + parser.accepts( "a", "some value you need" ).withRequiredArg().describedAs( "numerical" ) + .ofType( Integer.class ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "-a <Integer: numerical> some value you need", + EMPTY ); + } + + @Test + public void oneOptionOptionalArgNoDescription() throws Exception { + parser.accepts( "threshold" ).withOptionalArg(); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description", + "------ -----------", + "--threshold [String] ", + EMPTY ); + } + + @Test + public void oneOptionOptionalArgNoDescriptionWithType() throws Exception { + parser.accepts( "a" ).withOptionalArg().ofType( Float.class ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description", + "------ -----------", + "-a [Float] ", + EMPTY ); + } + + @Test + public void oneOptionOptionalArgWithDescription() throws Exception { + parser.accepts( "threshold", "some value you need" ).withOptionalArg().describedAs( "positive integer" ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "--threshold [String: positive integer] some value you need", + EMPTY ); + } + + @Test + public void oneOptionOptionalArgWithDescriptionAndType() throws Exception { + parser.accepts( "threshold", "some value you need" ).withOptionalArg().describedAs( "positive decimal" ) + .ofType( Double.class ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "--threshold [Double: positive decimal] some value you need", + EMPTY ); + } + + @Test + public void alternativeLongOptions() throws Exception { + parser.recognizeAlternativeLongOptions( true ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "-W <String: opt=value> Alternative form of long options", + EMPTY ); + } + + @Test + public void optionSynonymsWithoutArguments() throws Exception { + parser.acceptsAll( asList( "v", "chatty" ), "be verbose" ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description", + "------ -----------", + "-v, --chatty be verbose ", + EMPTY ); + } + + @Test + public void optionSynonymsWithRequiredArgument() throws Exception { + parser.acceptsAll( asList( "L", "index" ), "set level" ).withRequiredArg().ofType( Integer.class ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description", + "------ -----------", + "-L, --index <Integer> set level ", + EMPTY ); + } + + @Test + public void optionSynonymsWithOptionalArgument() throws Exception { + parser.acceptsAll( asList( "d", "since" ), "date filter" ).withOptionalArg().describedAs( "yyyyMMdd" ) + .ofType( Date.class ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description", + "------ -----------", + "-d, --since [Date: yyyyMMdd] date filter", + EMPTY ); + } + + @Test + public void optionSynonymsSortedByShortOptionThenLexicographical() throws Exception { + parser.acceptsAll( asList( "v", "prolix", "chatty" ) ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description", + "------ -----------", + "-v, --chatty, --prolix ", + EMPTY ); + } + + @Test + public void bothColumnsExceedingAllocatedWidths() throws Exception { + parser.acceptsAll( asList( "t", "threshold", "cutoff" ), + "a threshold value beyond which a certain level of the application should cease to write logs" ) + .withRequiredArg() + .describedAs( "a positive decimal number that will represent the threshold that has been outlined" ) + .ofType( Double.class ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "-t, --cutoff, --threshold <Double: a positive decimal a threshold value beyond which a certain level of the", + " number that will represent the threshold that has been application should cease to write logs ", + " outlined> ", + EMPTY ); + } + + // Bug 2018262 + @Test + public void gradleHelp() throws Exception { + parser.acceptsAll( asList( "n", "non-recursive" ), "Do not execute primary tasks of child projects." ); + parser.acceptsAll( singletonList( "S" ), + "Don't trigger a System.exit(0) for normal termination. Used for Gradle's internal testing." ); + parser.acceptsAll( asList( "I", "no-imports" ), "Disable usage of default imports for build script files." ); + parser.acceptsAll( asList( "u", "no-search-upward" ), + "Don't search in parent folders for a settings.gradle file." ); + parser.acceptsAll( asList( "x", "cache-off" ), "No caching of compiled build scripts." ); + parser.acceptsAll( asList( "r", "rebuild-cache" ), "Rebuild the cache of compiled build scripts." ); + parser.acceptsAll( asList( "v", "version" ), "Print version info." ); + parser.acceptsAll( asList( "d", "debug" ), "Log in debug mode (includes normal stacktrace)." ); + parser.acceptsAll( asList( "q", "quiet" ), "Log errors only." ); + parser.acceptsAll( asList( "j", "ivy-debug" ), "Set Ivy log level to debug (very verbose)." ); + parser.acceptsAll( asList( "i", "ivy-quiet" ), "Set Ivy log level to quiet." ); + parser.acceptsAll( asList( "s", "stacktrace" ), + "Print out the stacktrace also for user exceptions (e.g. compile error)." ); + parser.acceptsAll( asList( "f", "full-stacktrace" ), + "Print out the full (very verbose) stacktrace for any exceptions." ); + parser.acceptsAll( asList( "t", "tasks" ), "Show list of all available tasks and their dependencies." ); + parser.acceptsAll( asList( "p", "project-dir" ), + "Specifies the start dir for Gradle. Defaults to current dir." ).withRequiredArg().ofType( String.class ); + parser.acceptsAll( asList( "g", "gradle-user-home" ), "Specifies the gradle user home dir." ) + .withRequiredArg().ofType( String.class ); + parser.acceptsAll( asList( "l", "plugin-properties-file" ), "Specifies the plugin.properties file." ) + .withRequiredArg().ofType( String.class ); + parser.acceptsAll( asList( "b", "buildfile" ), + "Specifies the build file name (also for subprojects). Defaults to build.gradle." ) + .withRequiredArg().ofType( String.class ); + parser.acceptsAll( asList( "D", "systemprop" ), "Set system property of the JVM (e.g. -Dmyprop=myvalue)." ) + .withRequiredArg().ofType( String.class ); + parser.acceptsAll( asList( "P", "projectprop" ), + "Set project property for the build script (e.g. -Pmyprop=myvalue)." ) + .withRequiredArg().ofType( String.class ); + parser.acceptsAll( asList( "e", "embedded" ), "Specify an embedded build script." ) + .withRequiredArg().ofType( String.class ); + parser.acceptsAll( asList( "B", "bootstrap-debug" ), + "Specify a text to be logged at the beginning (e.g. used by Gradle's bootstrap class)." ) + .withRequiredArg().ofType( String.class ); + parser.acceptsAll( asList( "h", "?" ), "Shows this help message." ).forHelp(); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "-?, -h Shows this help message. ", + "-B, --bootstrap-debug <String> Specify a text to be logged at the beginning (e.g. used by Gradle's bootstrap ", + " class). ", + "-D, --systemprop <String> Set system property of the JVM (e.g. -Dmyprop=myvalue). ", + "-I, --no-imports Disable usage of default imports for build script files. ", + "-P, --projectprop <String> Set project property for the build script (e.g. -Pmyprop=myvalue). ", + "-S Don't trigger a System.exit(0) for normal termination. Used for Gradle's ", + " internal testing. ", + "-b, --buildfile <String> Specifies the build file name (also for subprojects). Defaults to build.gradle.", + "-d, --debug Log in debug mode (includes normal stacktrace). ", + "-e, --embedded <String> Specify an embedded build script. ", + "-f, --full-stacktrace Print out the full (very verbose) stacktrace for any exceptions. ", + "-g, --gradle-user-home <String> Specifies the gradle user home dir. ", + "-i, --ivy-quiet Set Ivy log level to quiet. ", + "-j, --ivy-debug Set Ivy log level to debug (very verbose). ", + "-l, --plugin-properties-file <String> Specifies the plugin.properties file. ", + "-n, --non-recursive Do not execute primary tasks of child projects. ", + "-p, --project-dir <String> Specifies the start dir for Gradle. Defaults to current dir. ", + "-q, --quiet Log errors only. ", + "-r, --rebuild-cache Rebuild the cache of compiled build scripts. ", + "-s, --stacktrace Print out the stacktrace also for user exceptions (e.g. compile error). ", + "-t, --tasks Show list of all available tasks and their dependencies. ", + "-u, --no-search-upward Don't search in parent folders for a settings.gradle file. ", + "-v, --version Print version info. ", + "-x, --cache-off No caching of compiled build scripts. ", + EMPTY ); + } + + @Test + public void dateConverterShowsDatePattern() throws Exception { + parser.accepts( "date", "a date" ).withRequiredArg().withValuesConvertedBy( datePattern( "MM/dd/yy" ) ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description", + "------ -----------", + "--date <MM/dd/yy> a date ", + EMPTY ); + } + + @Test + public void dateConverterShowsDatePatternInCombinationWithDescription() throws Exception { + parser.accepts( "date", "a date" ).withOptionalArg().describedAs( "your basic date pattern" ) + .withValuesConvertedBy( datePattern( "MM/dd/yy" ) ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description", + "------ -----------", + "--date [MM/dd/yy: your basic date pattern] a date ", + EMPTY ); + } + + @Test + public void leavesEmbeddedNewlinesInDescriptionsAlone() throws Exception { + List<String> descriptionPieces = + asList( "Specify the output type.", "'raw' = raw data.", "'java' = java class" ); + parser.accepts( "type", join( descriptionPieces, LINE_SEPARATOR ) ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "--type Specify the output type.", + " 'raw' = raw data. ", + " 'java' = java class ", + EMPTY ); + } + + @Test + public void includesDefaultValueForRequiredOptionArgument() throws Exception { + parser.accepts( "a" ).withRequiredArg().defaultsTo( "boo" ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "-a <String> (default: boo)", + EMPTY ); + } + + @Test + public void includesDefaultValueForOptionalOptionArgument() throws Exception { + parser.accepts( "b" ).withOptionalArg().ofType( Integer.class ).defaultsTo( 5 ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "-b [Integer] (default: 5)", + EMPTY ); + } + + @Test + public void includesDefaultValueForArgumentWithDescription() throws Exception { + parser.accepts( "c", "a quantity" ).withOptionalArg().ofType( BigDecimal.class ) + .describedAs( "quantity" ).defaultsTo( TEN ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "-c [BigDecimal: quantity] a quantity (default: 10)", + EMPTY ); + } + + @Test + public void includesListOfDefaultsForArgumentWithDescription() throws Exception { + parser.accepts( "d", "dizzle" ).withOptionalArg().ofType( Integer.class ) + .describedAs( "double dizzle" ).defaultsTo( 2, 3, 5, 7 ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "-d [Integer: double dizzle] dizzle (default: [2, 3, 5, 7])", + EMPTY ); + } + + @Test + public void marksRequiredOptionsSpecially() throws Exception { + parser.accepts( "e" ).withRequiredArg().required(); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option (* = required) Description", + "--------------------- -----------", + "* -e <String> ", + EMPTY ); + } + + private void assertHelpLines( String... expectedLines ) { + assertEquals( join( expectedLines, LINE_SEPARATOR ), sink.toString() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/CreateWithOptionSpecificationStringTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/CreateWithOptionSpecificationStringTest.java new file mode 100644 index 0000000000..545676ad12 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/CreateWithOptionSpecificationStringTest.java @@ -0,0 +1,51 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class CreateWithOptionSpecificationStringTest { + @Test + public void createsParserWithOptionSpecificationString() { + OptionParser first = new OptionParser() { + { + accepts( "i" ).withOptionalArg(); + accepts( "j" ).withRequiredArg(); + accepts( "k" ); + } + }; + + OptionParser second = new OptionParser( "i::j:k" ); + + String[] args = { "-k", "-ifoo", "-jbar" }; + assertEquals( first.parse( args ), second.parse( args ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/Ctor.java b/third_party/java/jopt-simple/src/test/java/joptsimple/Ctor.java new file mode 100644 index 0000000000..ad26a4de37 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/Ctor.java @@ -0,0 +1,45 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class Ctor { + private String s; + + public Ctor( String s ) { + this.s = s; + } + + public String getS() { + return s; + } + + static Ctor valueOf( String s ) { + return new Ctor( s ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/DefaultSettingsOptionParserHelpTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/DefaultSettingsOptionParserHelpTest.java new file mode 100644 index 0000000000..e9fd215b32 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/DefaultSettingsOptionParserHelpTest.java @@ -0,0 +1,753 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.StringWriter; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import joptsimple.util.InetAddressConverter; +import org.junit.Before; +import org.junit.Test; + +import static java.math.BigDecimal.*; +import static java.util.Arrays.*; +import static java.util.Collections.*; +import static joptsimple.internal.Strings.*; +import static joptsimple.util.DateConverter.*; +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class DefaultSettingsOptionParserHelpTest extends AbstractOptionParserFixture { + private StringWriter sink; + + @Before + public final void createSink() { + sink = new StringWriter(); + } + + @Test + public void unconfiguredParser() throws Exception { + parser.printHelpOn( sink ); + + assertHelpLines( "No options specified ", EMPTY ); + } + + @Test + public void repeatedCalls() throws Exception { + parser.accepts( "apple" ); + + parser.printHelpOn( sink ); + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description", + "------ -----------", + "--apple ", + "Option Description", + "------ -----------", + "--apple ", + EMPTY ); + } + + @Test + public void oneOptionNoArgNoDescription() throws Exception { + parser.accepts( "apple" ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description", + "------ -----------", + "--apple ", + EMPTY ); + } + + @Test + public void oneOptionNoArgWithDescription() throws Exception { + parser.accepts( "a", "some description" ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "-a some description", + EMPTY ); + } + + @Test + public void twoOptionsNoArgWithDescription() throws Exception { + parser.accepts( "a", "some description" ); + parser.accepts( "verbose", "even more description" ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "-a some description ", + "--verbose even more description", + EMPTY ); + } + + @Test + public void oneOptionRequiredArgNoDescription() throws Exception { + parser.accepts( "a" ).withRequiredArg(); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description", + "------ -----------", + "-a <String> ", + EMPTY ); + } + + @Test + public void oneOptionRequiredArgNoDescriptionWithType() throws Exception { + parser.accepts( "a" ).withRequiredArg().ofType( Integer.class ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description", + "------ -----------", + "-a <Integer> ", + EMPTY ); + } + + @Test + public void oneOptionRequiredArgWithDescription() throws Exception { + parser.accepts( "a", "some value you need" ).withRequiredArg().describedAs( "numerical" ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "-a <String: numerical> some value you need", + EMPTY ); + } + + @Test + public void oneOptionRequiredArgWithDescriptionAndType() throws Exception { + parser.accepts( "a", "some value you need" ) + .withRequiredArg().describedAs( "numerical" ).ofType( Integer.class ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "-a <Integer: numerical> some value you need", + EMPTY ); + } + + @Test + public void oneOptionOptionalArgNoDescription() throws Exception { + parser.accepts( "threshold" ).withOptionalArg(); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description", + "------ -----------", + "--threshold [String] ", + EMPTY ); + } + + @Test + public void oneOptionOptionalArgNoDescriptionWithType() throws Exception { + parser.accepts( "a" ).withOptionalArg().ofType( Float.class ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description", + "------ -----------", + "-a [Float] ", + EMPTY ); + } + + @Test + public void oneOptionOptionalArgWithDescription() throws Exception { + parser.accepts( "threshold", "some value you need" ).withOptionalArg().describedAs( "positive integer" ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "--threshold [String: positive integer] some value you need", + EMPTY ); + } + + @Test + public void oneOptionOptionalArgWithDescriptionAndType() throws Exception { + parser.accepts( "threshold", "some value you need" ) + .withOptionalArg().describedAs( "positive decimal" ).ofType( Double.class ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "--threshold [Double: positive decimal] some value you need", + EMPTY ); + } + + @Test + public void alternativeLongOptions() throws Exception { + parser.recognizeAlternativeLongOptions( true ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "-W <String: opt=value> Alternative form of long options", + EMPTY ); + } + + @Test + public void optionSynonymsWithoutArguments() throws Exception { + parser.acceptsAll( asList( "v", "chatty" ), "be verbose" ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description", + "------ -----------", + "-v, --chatty be verbose ", + EMPTY ); + } + + @Test + public void optionSynonymsWithRequiredArgument() throws Exception { + parser.acceptsAll( asList( "L", "index" ), "set level" ).withRequiredArg().ofType( Integer.class ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description", + "------ -----------", + "-L, --index <Integer> set level ", + EMPTY ); + } + + @Test + public void optionSynonymsWithOptionalArgument() throws Exception { + parser.acceptsAll( asList( "d", "since" ), "date filter" ) + .withOptionalArg().describedAs( "yyyyMMdd" ).ofType( Date.class ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description", + "------ -----------", + "-d, --since [Date: yyyyMMdd] date filter", + EMPTY ); + } + + @Test + public void optionSynonymsSortedByShortOptionThenLexicographical() throws Exception { + parser.acceptsAll( asList( "v", "prolix", "chatty" ) ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description", + "------ -----------", + "-v, --chatty, --prolix ", + EMPTY ); + } + + @Test + public void writingToOutputStream() throws Exception { + ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); + + parser.printHelpOn( bytesOut ); + + assertEquals( "No options specified " + LINE_SEPARATOR, bytesOut.toString() ); + } + + // Bug 1956418 + @Test + public void outputStreamFlushedButNotClosedWhenPrintingHelp() throws Exception { + FakeOutputStream fake = new FakeOutputStream(); + + parser.printHelpOn( fake ); + + assertTrue( fake.flushed ); + assertFalse( fake.closed ); + } + + @Test + public void bothColumnsExceedingAllocatedWidths() throws Exception { + parser.acceptsAll( asList( "t", "threshold", "cutoff" ), + "a threshold value beyond which a certain level of the application should cease to write logs" ) + .withRequiredArg() + .describedAs( "a positive decimal number that will represent the threshold that has been outlined" ) + .ofType( Double.class ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "-t, --cutoff, --threshold <Double: a a threshold value beyond which a ", + " positive decimal number that will certain level of the application", + " represent the threshold that has should cease to write logs ", + " been outlined> ", + EMPTY ); + } + + // Bug 2018262 + @Test + public void gradleHelp() throws Exception { + parser.acceptsAll( asList( "n", "non-recursive" ), + "Do not execute primary tasks of child projects." ); + parser.acceptsAll( singletonList( "S" ), + "Don't trigger a System.exit(0) for normal termination. Used for Gradle's internal testing." ); + parser.acceptsAll( asList( "I", "no-imports" ), + "Disable usage of default imports for build script files." ); + parser.acceptsAll( asList( "u", "no-search-upward" ), + "Don't search in parent folders for a settings.gradle file." ); + parser.acceptsAll( asList( "x", "cache-off" ), + "No caching of compiled build scripts." ); + parser.acceptsAll( asList( "r", "rebuild-cache" ), + "Rebuild the cache of compiled build scripts." ); + parser.acceptsAll( asList( "v", "version" ), "Print version info." ); + parser.acceptsAll( asList( "d", "debug" ), + "Log in debug mode (includes normal stacktrace)." ); + parser.acceptsAll( asList( "q", "quiet" ), "Log errors only." ); + parser.acceptsAll( asList( "j", "ivy-debug" ), + "Set Ivy log level to debug (very verbose)." ); + parser.acceptsAll( asList( "i", "ivy-quiet" ), "Set Ivy log level to quiet." ); + parser.acceptsAll( asList( "s", "stacktrace" ), + "Print out the stacktrace also for user exceptions (e.g. compile error)." ); + parser.acceptsAll( asList( "f", "full-stacktrace" ), + "Print out the full (very verbose) stacktrace for any exceptions." ); + parser.acceptsAll( asList( "t", "tasks" ), + "Show list of all available tasks and their dependencies." ); + parser.acceptsAll( asList( "p", "project-dir" ), + "Specifies the start dir for Gradle. Defaults to current dir." ) + .withRequiredArg().ofType( String.class ); + parser.acceptsAll( asList( "g", "gradle-user-home" ), + "Specifies the gradle user home dir." ) + .withRequiredArg().ofType( String.class ); + parser.acceptsAll( asList( "l", "plugin-properties-file" ), + "Specifies the plugin.properties file." ) + .withRequiredArg().ofType( String.class ); + parser.acceptsAll( asList( "b", "buildfile" ), + "Specifies the build file name (also for subprojects). Defaults to build.gradle." ) + .withRequiredArg().ofType( String.class ); + parser.acceptsAll( asList( "D", "systemprop" ), + "Set system property of the JVM (e.g. -Dmyprop=myvalue)." ) + .withRequiredArg().ofType( String.class ); + parser.acceptsAll( asList( "P", "projectprop" ), + "Set project property for the build script (e.g. -Pmyprop=myvalue)." ) + .withRequiredArg().ofType( String.class ); + parser.acceptsAll( asList( "e", "embedded" ), + "Specify an embedded build script." ) + .withRequiredArg().ofType( String.class ); + parser.acceptsAll( asList( "B", "bootstrap-debug" ), + "Specify a text to be logged at the beginning (e.g. used by Gradle's bootstrap class)." ) + .withRequiredArg().ofType( String.class ); + parser.acceptsAll( asList( "h", "?" ), "Shows this help message" ).forHelp(); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "-?, -h Shows this help message ", + "-B, --bootstrap-debug <String> Specify a text to be logged at the ", + " beginning (e.g. used by Gradle's ", + " bootstrap class). ", + "-D, --systemprop <String> Set system property of the JVM (e.g. - ", + " Dmyprop=myvalue). ", + "-I, --no-imports Disable usage of default imports for ", + " build script files. ", + "-P, --projectprop <String> Set project property for the build ", + " script (e.g. -Pmyprop=myvalue). ", + "-S Don't trigger a System.exit(0) for ", + " normal termination. Used for Gradle's ", + " internal testing. ", + "-b, --buildfile <String> Specifies the build file name (also for ", + " subprojects). Defaults to build.gradle.", + "-d, --debug Log in debug mode (includes normal ", + " stacktrace). ", + "-e, --embedded <String> Specify an embedded build script. ", + "-f, --full-stacktrace Print out the full (very verbose) ", + " stacktrace for any exceptions. ", + "-g, --gradle-user-home <String> Specifies the gradle user home dir. ", + "-i, --ivy-quiet Set Ivy log level to quiet. ", + "-j, --ivy-debug Set Ivy log level to debug (very ", + " verbose). ", + "-l, --plugin-properties-file <String> Specifies the plugin.properties file. ", + "-n, --non-recursive Do not execute primary tasks of child ", + " projects. ", + "-p, --project-dir <String> Specifies the start dir for Gradle. ", + " Defaults to current dir. ", + "-q, --quiet Log errors only. ", + "-r, --rebuild-cache Rebuild the cache of compiled build ", + " scripts. ", + "-s, --stacktrace Print out the stacktrace also for user ", + " exceptions (e.g. compile error). ", + "-t, --tasks Show list of all available tasks and ", + " their dependencies. ", + "-u, --no-search-upward Don't search in parent folders for a ", + " settings.gradle file. ", + "-v, --version Print version info. ", + "-x, --cache-off No caching of compiled build scripts. ", + EMPTY ); + } + + @Test + public void dateConverterShowsDatePattern() throws Exception { + parser.accepts( "date", "a date" ) + .withRequiredArg() + .withValuesConvertedBy( datePattern( "MM/dd/yy" ) ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description", + "------ -----------", + "--date <MM/dd/yy> a date ", + EMPTY ); + } + + @Test + public void dateConverterShowsDatePatternInCombinationWithDescription() throws Exception { + parser.accepts( "date", "a date" ).withOptionalArg() + .describedAs( "your basic date pattern" ) + .withValuesConvertedBy( datePattern( "MM/dd/yy" ) ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description", + "------ -----------", + "--date [MM/dd/yy: your basic date a date ", + " pattern] ", + EMPTY ); + } + + @Test + public void inetAddressConverterShowsType() throws Exception { + parser.accepts( "addr", "an internet address" ) + .withRequiredArg() + .withValuesConvertedBy( new InetAddressConverter() ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "--addr <InetAddress> an internet address", + EMPTY ); + } + + @Test + public void leavesEmbeddedNewlinesInDescriptionsAlone() throws Exception { + List<String> descriptionPieces = + asList( "Specify the output type.", "'raw' = raw data.", "'java' = java class" ); + parser.accepts( "type", join( descriptionPieces, LINE_SEPARATOR ) ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "--type Specify the output type.", + " 'raw' = raw data. ", + " 'java' = java class ", + EMPTY ); + } + + @Test + public void includesDefaultValueForRequiredOptionArgument() throws Exception { + parser.accepts( "a" ).withRequiredArg().defaultsTo( "boo" ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "-a <String> (default: boo)", + EMPTY ); + } + + @Test + public void includesDefaultValueForOptionalOptionArgument() throws Exception { + parser.accepts( "b" ).withOptionalArg().ofType( Integer.class ).defaultsTo( 5 ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "-b [Integer] (default: 5)", + EMPTY ); + } + + @Test + public void includesDefaultValueForArgumentWithDescription() throws Exception { + parser.accepts( "c", "a quantity" ).withOptionalArg().ofType( BigDecimal.class ) + .describedAs( "quantity" ).defaultsTo( TEN ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "-c [BigDecimal: quantity] a quantity (default: 10)", + EMPTY ); + } + + @Test + public void includesListOfDefaultsForArgumentWithDescription() throws Exception { + parser.accepts( "d", "dizzle" ).withOptionalArg().ofType( Integer.class ) + .describedAs( "double dizzle" ).defaultsTo( 2, 3, 5, 7 ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "-d [Integer: double dizzle] dizzle (default: [2, 3, 5, 7])", + EMPTY ); + } + + @Test + public void marksRequiredOptionsSpecially() throws Exception { + parser.accepts( "e" ).withRequiredArg().required(); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option (* = required) Description", + "--------------------- -----------", + "* -e <String> ", + EMPTY ); + } + + @Test + public void showsNonOptionArgumentDescription() throws Exception { + parser.nonOptions( "stuff" ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Non-option arguments:", + "[String] -- stuff ", + EMPTY, + "No options specified ", + EMPTY ); + } + + @Test + public void showsNonOptionArgumentType() throws Exception { + parser.nonOptions().ofType( File.class ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Non-option arguments:", + "[File] ", + EMPTY, + "No options specified ", + EMPTY ); + } + + @Test + public void showsNonOptionArgumentTypeDescribedAs() throws Exception { + parser.nonOptions().describedAs( "files" ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Non-option arguments:", + "[String: files] ", + EMPTY, + "No options specified ", + EMPTY ); + } + + @Test + public void showsNonOptionArgumentTypeAndArgumentDescription() throws Exception { + parser.nonOptions().ofType( File.class ).describedAs( "files" ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Non-option arguments:", + "[File: files] ", + EMPTY, + "No options specified ", + EMPTY ); + } + + @Test + public void showsNonOptionArgumentTypeAndDescription() throws Exception { + parser.nonOptions( "some files to operate on" ).ofType( File.class ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Non-option arguments: ", + "[File] -- some files to operate on", + EMPTY, + "No options specified ", + EMPTY ); + } + + @Test + public void showsNonOptionArgumentTypeAndDescriptionAndArgumentDescription() throws Exception { + parser.nonOptions( "some files to operate on" ).ofType( File.class ).describedAs( "files" ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Non-option arguments: ", + "[File: files] -- some files to operate on", + EMPTY, + "No options specified ", + EMPTY ); + } + + @Test + public void canUseCustomHelpFormatter() { + parser.accepts( "f" ); + + parser.formatHelpWith( new HelpFormatter() { + public String format( Map<String, ? extends OptionDescriptor> options ) { + assertEquals( 1, options.size() ); + OptionDescriptor only = options.get( "f" ); + assertEquals( asList( "f" ), new ArrayList<>( only.options() ) ); + assertFalse( only.acceptsArguments() ); + assertEquals( "", only.argumentDescription() ); + assertEquals( "", only.argumentTypeIndicator() ); + assertEquals( emptyList(), only.defaultValues() ); + assertEquals( "", only.description() ); + assertFalse( only.isRequired() ); + assertFalse( only.requiresArgument() ); + return null; + } + } ); + } + + @Test( expected = NullPointerException.class ) + public void rejectsNullHelpFormatter() { + parser.formatHelpWith( null ); + } + + @Test + public void fixForIssue56() throws Exception { + parser.accepts( "password", "Server Password" ).withRequiredArg().ofType( String.class ); + parser.accepts( "F", "Forward port mapping (ie: localhost:5900:localhost:5900)" ).withRequiredArg(); + parser.accepts( "R", "Reverse port mapping (ie: localhost:5900:localhost:5900)" ).withRequiredArg(); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "-F <String> Forward port mapping (ie: localhost:5900:localhost:5900)", + "-R <String> Reverse port mapping (ie: localhost:5900:localhost:5900)", + "--password <String> Server Password ", + EMPTY ); + } + + @Test + public void fixForIssue85() throws Exception { + parser.acceptsAll( asList( "?", "help" ), "Display this help text" ).forHelp(); + parser.acceptsAll( asList( "c", "check-avail" ), + "Check Galileo homepage for available books, compare with known ones" ); + parser.acceptsAll( asList( "d", "download-dir" ), + "Download directory for openbooks; must exist" ) + .withRequiredArg().ofType( File.class ).defaultsTo( new File( "." ) ); + parser.acceptsAll( asList( "l", "log-level" ), + "Log level (0=normal, 1=verbose, 2=debug, 3=trace" ) + .withRequiredArg().ofType( int.class ).defaultsTo( 0 ); + parser.acceptsAll( asList( "m", "check-md5" ), + "Download all known books without storing them, verifying their MD5 checksum (slow! >1 Gb download)" ); + parser.acceptsAll( asList( "t", "threading" ), + "Threading mode (0=single, 1=multi); single is slower, but better for diagnostics)" ) + .withRequiredArg().ofType( int.class ).defaultsTo( 1 ); + parser.acceptsAll( asList( "w", "write-config" ), + "Write editable book list to config.xml, enabling you to update MD5 checksums or add new books" ); + + parser.printHelpOn( sink ); + + assertHelpLines( + "Option Description ", + "------ ----------- ", + "-?, --help Display this help text ", + "-c, --check-avail Check Galileo homepage for available books, compare ", + " with known ones ", + "-d, --download-dir <File> Download directory for openbooks; must exist ", + " (default: .) ", + "-l, --log-level <Integer> Log level (0=normal, 1=verbose, 2=debug, 3=trace ", + " (default: 0) ", + "-m, --check-md5 Download all known books without storing them, ", + " verifying their MD5 checksum (slow! >1 Gb download)", + "-t, --threading <Integer> Threading mode (0=single, 1=multi); single is ", + " slower, but better for diagnostics) (default: 1) ", + "-w, --write-config Write editable book list to config.xml, enabling you ", + " to update MD5 checksums or add new books ", + EMPTY ); + } + + private void assertHelpLines( String... expectedLines ) { + assertEquals( join( expectedLines, LINE_SEPARATOR ), sink.toString() ); + } + + static class FakeOutputStream extends ByteArrayOutputStream { + boolean closed; + boolean flushed; + + @Override + public void close() { + this.closed = true; + } + + @Override + public void flush() { + this.flushed = true; + } + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/EmptyOptionSetTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/EmptyOptionSetTest.java new file mode 100644 index 0000000000..640f0ff90f --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/EmptyOptionSetTest.java @@ -0,0 +1,87 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.Collections; +import static java.util.Collections.*; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class EmptyOptionSetTest { + private OptionSet empty; + + @Before + public void setUp() { + empty = new OptionSet( Collections.<String, AbstractOptionSpec<?>> emptyMap() ); + empty.add( new NonOptionArgumentSpec<>() ); + } + + @Test + public void valueOf() { + assertNull( empty.valueOf( "a" ) ); + } + + @Test + public void valuesOf() { + assertEquals( emptyList(), empty.valuesOf( "a" ) ); + } + + @Test + public void hasArgument() { + assertFalse( empty.hasArgument( "a" ) ); + } + + @Test + public void hasOptions() { + assertFalse( empty.hasOptions() ); + } + + @Test( expected = NullPointerException.class ) + public void valueOfWithNullString() { + empty.valueOf( (String) null ); + } + + @Test( expected = NullPointerException.class ) + public void valueOfWithNullOptionSpec() { + empty.valueOf( (OptionSpec<?>) null ); + } + + @Test( expected = NullPointerException.class ) + public void valuesOfWithNullString() { + empty.valuesOf( (String) null ); + } + + @Test( expected = NullPointerException.class ) + public void valuesOfWithNullOptionSpec() { + empty.valuesOf( (OptionSpec<?>) null ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ExceptionMatchers.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ExceptionMatchers.java new file mode 100644 index 0000000000..5299fef2b9 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ExceptionMatchers.java @@ -0,0 +1,83 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.lang.reflect.InvocationTargetException; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class ExceptionMatchers { + private ExceptionMatchers() { + throw new UnsupportedOperationException(); + } + + public static Matcher<OptionException> withOption( final String option ) { + return new TypeSafeMatcher<OptionException>() { + @Override + public boolean matchesSafely( OptionException target ) { + return target.options().contains( option ); + } + + public void describeTo( Description description ) { + description.appendText( "an OptionException indicating the option "); + description.appendValue( option ); + } + }; + } + + public static Matcher<Throwable> withCauseOfType( final Class<? extends Throwable> type ) { + return new TypeSafeMatcher<Throwable>() { + @Override + public boolean matchesSafely( Throwable target ) { + return type.isInstance( target.getCause() ); + } + + public void describeTo( Description description ) { + description.appendText( "an exception with cause of type " ); + description.appendValue( type ); + } + }; + } + + public static Matcher<InvocationTargetException> withTargetOfType( final Class<? extends Throwable> type ) { + return new TypeSafeMatcher<InvocationTargetException>() { + @Override + public boolean matchesSafely( InvocationTargetException target ) { + return type.isInstance( target.getTargetException() ); + } + + public void describeTo( Description description ) { + description.appendText( "an InvocationTargetException with target of type " ); + description.appendValue( type ); + } + }; + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/HandlingDefaultValuesForOptionArgumentsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/HandlingDefaultValuesForOptionArgumentsTest.java new file mode 100644 index 0000000000..5ed3141b97 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/HandlingDefaultValuesForOptionArgumentsTest.java @@ -0,0 +1,183 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.math.BigDecimal; +import java.util.List; + +import static java.math.BigDecimal.*; +import static java.util.Arrays.*; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class HandlingDefaultValuesForOptionArgumentsTest extends AbstractOptionParserFixture { + @Test + public void requiredArgOptionWithDefaultGivesArgIfArgSpecifiedOnCommandLine() { + OptionSpec<Integer> optionA = + parser.accepts( "a" ).withRequiredArg().ofType( Integer.class ).defaultsTo( 2 ); + + OptionSet options = parser.parse( "-a", "1" ); + + assertTrue( options.has( "a" ) ); + assertTrue( options.has( optionA ) ); + assertTrue( options.hasArgument( "a" ) ); + assertTrue( options.hasArgument( optionA ) ); + Integer expectedArgument = 1; + assertEquals( expectedArgument, options.valueOf( "a" ) ); + assertEquals( expectedArgument, options.valueOf( optionA ) ); + assertEquals( expectedArgument, optionA.value( options ) ); + assertEquals( asList( expectedArgument ), options.valuesOf( "a" ) ); + assertEquals( asList( expectedArgument ), options.valuesOf( optionA ) ); + assertEquals( asList( expectedArgument ), optionA.values( options ) ); + } + + @Test( expected = OptionMissingRequiredArgumentException.class ) + public void requiredArgOptionWithDefaultStillsFailToParseIfArgNotSpecifiedOnCommandLine() { + parser.accepts( "a" ).withRequiredArg().defaultsTo( "boo" ); + + parser.parse( "-a" ); + } + + @Test + public void optionalArgOptionWithDefaultGivesDefaultIfArgNotSpecifiedOnCommandLine() { + OptionSpec<Long> optionA = + parser.accepts( "a" ).withOptionalArg().ofType( Long.class ).defaultsTo( -1L ); + + OptionSet options = parser.parse( "-a" ); + + assertTrue( options.has( "a" ) ); + assertTrue( options.has( optionA ) ); + assertFalse( options.hasArgument( "a" ) ); + assertFalse( options.hasArgument( optionA ) ); + Long expectedArgument = -1L; + assertEquals( expectedArgument, options.valueOf( "a" ) ); + assertEquals( expectedArgument, options.valueOf( optionA ) ); + assertEquals( expectedArgument, optionA.value( options ) ); + assertEquals( asList( expectedArgument ), options.valuesOf( "a" ) ); + assertEquals( asList( expectedArgument ), options.valuesOf( optionA ) ); + assertEquals( asList( expectedArgument ), optionA.values( options ) ); + } + + @Test + public void optionalArgOptionWithDefaultGivesArgIfSpecifiedOnCommandLine() { + OptionSpec<Long> optionA = + parser.accepts( "a" ).withOptionalArg().ofType( Long.class ).defaultsTo( -1L ); + + OptionSet options = parser.parse( "-a", "2" ); + + assertTrue( options.has( "a" ) ); + assertTrue( options.has( optionA ) ); + assertTrue( options.hasArgument( "a" ) ); + assertTrue( options.hasArgument( optionA ) ); + Long expectedArgument = 2L; + assertEquals( expectedArgument, options.valueOf( "a" ) ); + assertEquals( expectedArgument, options.valueOf( optionA ) ); + assertEquals( expectedArgument, optionA.value( options ) ); + assertEquals( asList( expectedArgument ), options.valuesOf( "a" ) ); + assertEquals( asList( expectedArgument ), options.valuesOf( optionA ) ); + assertEquals( asList( expectedArgument ), optionA.values( options ) ); + } + + @Test + public void requiredArgOptionWithDefaultGivesDefaultIfOptionNotOnCommandLine() { + OptionSpec<BigDecimal> optionA = + parser.accepts( "a" ).withRequiredArg().ofType( BigDecimal.class ).defaultsTo( TEN ); + + OptionSet options = parser.parse(); + + assertFalse( options.has( "a" ) ); + assertFalse( options.has( optionA ) ); + assertFalse( options.hasArgument( "a" ) ); + assertFalse( options.hasArgument( optionA ) ); + assertEquals( TEN, options.valueOf( "a" ) ); + assertEquals( TEN, options.valueOf( optionA ) ); + assertEquals( TEN, optionA.value( options ) ); + assertEquals( asList( TEN ), options.valuesOf( "a" ) ); + assertEquals( asList( TEN ), options.valuesOf( optionA ) ); + assertEquals( asList( TEN ), optionA.values( options ) ); + } + + @Test + public void optionalArgOptionWithDefaultGivesDefaultIfOptionNotOnCommandLine() { + OptionSpec<BigDecimal> optionA = + parser.accepts( "a" ).withOptionalArg().ofType( BigDecimal.class ).defaultsTo( TEN ); + + OptionSet options = parser.parse(); + + assertFalse( options.has( "a" ) ); + assertFalse( options.has( optionA ) ); + assertFalse( options.hasArgument( "a" ) ); + assertFalse( options.hasArgument( optionA ) ); + assertEquals( TEN, options.valueOf( "a" ) ); + assertEquals( TEN, options.valueOf( optionA ) ); + assertEquals( TEN, optionA.value( options ) ); + assertEquals( asList( TEN ), options.valuesOf( "a" ) ); + assertEquals( asList( TEN ), options.valuesOf( optionA ) ); + assertEquals( asList( TEN ), optionA.values( options ) ); + } + + @Test + public void allowsListOfDefaults() { + OptionSpec<Integer> optionC = + parser.accepts( "c" ).withOptionalArg().ofType( Integer.class ).defaultsTo( 1, 2, 3 ); + + OptionSet options = parser.parse(); + + List<Integer> expected = asList( 1, 2, 3 ); + assertEquals( expected, optionC.values( options ) ); + assertEquals( expected, options.valuesOf( optionC ) ); + } + + @Test + public void specifiedOptionArgumentsTrumpsListOfDefaults() { + OptionSpec<Integer> optionC = + parser.accepts( "c" ).withRequiredArg().ofType( Integer.class ) + .defaultsTo( 1, 2, 3 ).withValuesSeparatedBy( ',' ); + + OptionSet options = parser.parse( "-c", "4", "-c", "5", "-c", "6,7,8" ); + + List<Integer> expected = asList( 4, 5, 6, 7, 8 ); + assertEquals( expected, optionC.values( options ) ); + assertEquals( expected, options.valuesOf( optionC ) ); + } + + @Test + public void withCompileTimeArraySpecifyingDefaults() { + OptionSpec<Integer> optionD = + parser.accepts( "d" ).withRequiredArg().ofType( Integer.class ).defaultsTo( new Integer[] { 1, 2, 3 } ); + + OptionSet options = parser.parse(); + + List<Integer> expected = asList( 1, 2, 3 ); + assertEquals( expected, optionD.values( options ) ); + assertEquals( expected, options.valuesOf( optionD ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/InterleavedArgumentsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/InterleavedArgumentsTest.java new file mode 100644 index 0000000000..e91fbd3210 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/InterleavedArgumentsTest.java @@ -0,0 +1,140 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Arrays.*; +import static java.util.Collections.*; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class InterleavedArgumentsTest { + @Test + public void onlyAppearingToHaveOptionArguments() { + OptionParser parser = new OptionParser( "c" ); + + OptionSet options = parser.parse( "-c", "a", "-c", "b", "-c", "c", "-c", "d" ); + + assertTrue( options.has( "c" ) ); + assertEquals( emptyList(), options.valuesOf( "c" ) ); + assertEquals( asList( "a", "b", "c", "d" ), options.nonOptionArguments() ); + } + + @Test + public void onlyAppearingToHaveOptionArgumentsButPosixlyCorrect() { + OptionParser parser = new OptionParser( "+c" ); + + OptionSet options = parser.parse( "-c", "a", "-c", "b", "-c", "c", "-c", "d" ); + + assertTrue( options.has( "c" ) ); + assertEquals( emptyList(), options.valuesOf( "c" ) ); + assertEquals( + asList( "a", "-c", "b", "-c", "c", "-c", "d" ), + options.nonOptionArguments() ); + } + + @Test + public void requiredArgument() { + OptionParser parser = new OptionParser( "c:" ); + + OptionSet options = parser.parse( "-c", "a", "-c", "b", "-c", "c", "-c", "d" ); + + assertTrue( options.has( "c" ) ); + assertEquals( asList( "a", "b", "c", "d" ), options.valuesOf( "c" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void requiredArgumentAndPosixlyCorrect() { + OptionParser parser = new OptionParser( "+c:" ); + + OptionSet options = parser.parse( "-c", "a", "-c", "b", "-c", "c", "-c", "d" ); + + assertTrue( options.has( "c" ) ); + assertEquals( asList( "a", "b", "c", "d" ), options.valuesOf( "c" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void optionalArgument() { + OptionParser parser = new OptionParser( "c::" ); + + OptionSet options = parser.parse( "-c", "a", "-c", "b", "-c", "c", "-c", "d" ); + + assertTrue( options.has( "c" ) ); + assertEquals( asList( "a", "b", "c", "d" ), options.valuesOf( "c" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void optionalArgumentAndPosixlyCorrect() { + OptionParser parser = new OptionParser( "+c::" ); + + OptionSet options = parser.parse( "-c", "a", "-c", "b", "-c", "c", "-c", "d" ); + + assertTrue( options.has( "c" ) ); + assertEquals( emptyList(), options.valuesOf( "c" ) ); + assertEquals( asList( "a", "-c", "b", "-c", "c", "-c", "d" ), options.nonOptionArguments() ); + } + + @Test + public void leadingNonOptionCausesPosixlyCorrectToIgnoreRemainder() { + OptionParser parser = new OptionParser( "+c:" ); + String[] args = { "boo", "-c", "a", "-c", "b", "-c", "c", "-c", "d" }; + + OptionSet options = parser.parse( args ); + + assertFalse( options.has( "c" ) ); + assertEquals( emptyList(), options.valuesOf( "c" ) ); + assertEquals( asList( args ), options.nonOptionArguments() ); + } + + @Test + public void optionalAbuttedArgumentVersusPosixlyCorrect() { + OptionParser parser = new OptionParser( "+c::" ); + + OptionSet options = parser.parse( "-ca", "-cb", "-c", "c", "-c", "d" ); + + assertTrue( options.has( "c" ) ); + assertEquals( asList( "a", "b" ), options.valuesOf( "c" ) ); + assertEquals( asList( "c", "-c", "d" ), options.nonOptionArguments() ); + } + + @Test + public void optionalKeyValuePairArgumentVersusPosixlyCorrect() { + OptionParser parser = new OptionParser( "+c::" ); + + OptionSet options = parser.parse( "-c=a", "-c=b", "-c", "c", "-c", "d" ); + + assertTrue( options.has( "c" ) ); + assertEquals( asList( "a", "b" ), options.valuesOf( "c" ) ); + assertEquals( asList( "c", "-c", "d" ), options.nonOptionArguments() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/Issue76Test.java b/third_party/java/jopt-simple/src/test/java/joptsimple/Issue76Test.java new file mode 100644 index 0000000000..31221deba7 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/Issue76Test.java @@ -0,0 +1,71 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import org.junit.Before; +import org.junit.Test; + +import static java.util.Arrays.asList; +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class Issue76Test { + private OptionParser parser; + private OptionSpec<Integer> nonOptions; + + @Before + public void setUp() { + parser = new OptionParser(); + parser.accepts( "flag" ).withOptionalArg().withValuesConvertedBy( new ValueConverter<Boolean>() { + public Boolean convert( String value ) { + if ( "true".equals( value ) ) + return true; + if ( "false".equals( value ) ) + return false; + throw new ValueConversionException( "need 'true' or 'false'" ); + } + + public Class<? extends Boolean> valueType() { + return boolean.class; + } + + public String valuePattern() { + return null; + } + }); + nonOptions = parser.nonOptions().ofType( Integer.class ); + } + + @Test + public void suppliedExample() { + OptionSet parsed = parser.parse( "--flag", "1", "2" ); + + assertTrue( parsed.has( "flag" ) ); + assertEquals( asList( 1, 2 ), nonOptions.values( parsed ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/JVMSystemPropertiesArgumentParsingTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/JVMSystemPropertiesArgumentParsingTest.java new file mode 100644 index 0000000000..49366cf0fb --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/JVMSystemPropertiesArgumentParsingTest.java @@ -0,0 +1,53 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Arrays.*; + +import joptsimple.util.KeyValuePair; +import org.junit.Before; +import org.junit.Test; + +import static joptsimple.util.KeyValuePair.*; +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class JVMSystemPropertiesArgumentParsingTest extends AbstractOptionParserFixture { + @Before + public final void initializeParser() { + parser.accepts( "D" ).withRequiredArg().ofType( KeyValuePair.class ); + } + + @Test + public void parsingJVMSystemPropertiesArguments() { + OptionSet options = parser.parse( "-Dfile.encoding=UTF-8", "-Dpath.separator=:" ); + assertEquals( + asList( valueOf( "file.encoding=UTF-8" ), valueOf( "path.separator=:" ) ), + options.valuesOf( "D" ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/LongOptionNoArgumentTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/LongOptionNoArgumentTest.java new file mode 100644 index 0000000000..c41f9bbd66 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/LongOptionNoArgumentTest.java @@ -0,0 +1,82 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Collections.*; + +import org.junit.Before; +import org.junit.Test; + +import static joptsimple.ExceptionMatchers.*; +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class LongOptionNoArgumentTest extends AbstractOptionParserFixture { + @Before + public final void initializeParser() { + parser.accepts( "verbose" ); + parser.accepts( "verb" ); + } + + @Test + public void singleLongOption() { + OptionSet options = parser.parse( "--verbose" ); + + assertTrue( options.has( "verbose" ) ); + assertEquals( emptyList(), options.valuesOf( "verbose" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void singleLongOptionAbbreviated() { + OptionSet options = parser.parse( "--verbo" ); + + assertTrue( options.has( "verbose" ) ); + assertFalse( options.has( "verb" ) ); + assertEquals( emptyList(), options.valuesOf( "verbose" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void abbreviationIsALegalOption() { + OptionSet options = parser.parse( "--verb" ); + + assertFalse( options.has( "verbose" ) ); + assertTrue( options.has( "verb" ) ); + assertEquals( emptyList(), options.valuesOf( "verb" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void ambiguousAbbreviation() { + thrown.expect( UnrecognizedOptionException.class ); + thrown.expect( withOption( "ver" ) ); + + parser.parse( "--ver" ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/LongOptionOptionalArgumentTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/LongOptionOptionalArgumentTest.java new file mode 100644 index 0000000000..93e4b4d394 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/LongOptionOptionalArgumentTest.java @@ -0,0 +1,72 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Collections.*; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class LongOptionOptionalArgumentTest extends AbstractOptionParserFixture { + @Before + public final void initializeParser() { + parser.accepts( "output" ).withOptionalArg(); + parser.accepts( "a" ); + } + + @Test + public void argumentMissingTrailedByAnotherOption() { + OptionSet options = parser.parse( "--output", "-a" ); + + assertTrue( options.has( "output" ) ); + assertTrue( options.has( "a" ) ); + assertEquals( emptyList(), options.valuesOf( "output" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void argumentSeparate() { + OptionSet options = parser.parse( "--output", "opt" ); + + assertTrue( options.has( "output" ) ); + assertEquals( singletonList( "opt" ), options.valuesOf( "output" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void argumentTogether() { + OptionSet options = parser.parse( "--output=opt" ); + + assertTrue( options.has( "output" ) ); + assertEquals( singletonList( "opt" ), options.valuesOf( "output" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/LongOptionRequiredArgumentTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/LongOptionRequiredArgumentTest.java new file mode 100644 index 0000000000..fe77f06259 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/LongOptionRequiredArgumentTest.java @@ -0,0 +1,103 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Collections.*; + +import org.junit.Before; +import org.junit.Test; + +import static joptsimple.ExceptionMatchers.*; +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class LongOptionRequiredArgumentTest extends AbstractOptionParserFixture { + @Before + public final void initializeParser() { + parser.accepts( "quiet" ).withRequiredArg(); + parser.accepts( "a" ).withOptionalArg(); + parser.accepts( "y" ).withRequiredArg(); + } + + @Test + public void argumentSeparate() { + OptionSet options = parser.parse( "--quiet", "23" ); + + assertOptionDetected( options, "quiet" ); + assertEquals( singletonList( "23" ), options.valuesOf( "quiet" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void argumentFollowedByLegalOption() { + OptionSet options = parser.parse( "--quiet", "-a" ); + + assertOptionDetected( options, "quiet" ); + assertOptionNotDetected( options, "a" ); + assertEquals( singletonList( "-a" ), options.valuesOf( "quiet" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void argumentTogether() { + OptionSet options = parser.parse( "--quiet=23" ); + + assertOptionDetected( options, "quiet" ); + assertEquals( singletonList( "23" ), options.valuesOf( "quiet" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void argumentMissing() { + thrown.expect( OptionMissingRequiredArgumentException.class ); + thrown.expect( withOption( "quiet" ) ); + + parser.parse( "--quiet" ); + } + + @Test + public void shortOptionSpecifiedAsLongOptionWithArgument() { + OptionSet options = parser.parse( "--y=bar" ); + + assertOptionDetected( options, "y" ); + assertEquals( singletonList( "bar" ), options.valuesOf( "y" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void whenEndOfOptionsMarkerIsInPlaceOfRequiredArgument() { + OptionSet options = parser.parse( "--quiet", "--", "-y", "foo", "-a" ); + + assertOptionDetected( options, "quiet" ); + assertOptionDetected( options, "y" ); + assertOptionDetected( options, "a" ); + assertEquals( singletonList( "--" ), options.valuesOf( "quiet" ) ); + assertEquals( singletonList( "foo" ), options.valuesOf( "y" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/NoArgumentOptionSpecOptionsImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/NoArgumentOptionSpecOptionsImmutabilityTest.java new file mode 100644 index 0000000000..ec9e6a79eb --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/NoArgumentOptionSpecOptionsImmutabilityTest.java @@ -0,0 +1,36 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class NoArgumentOptionSpecOptionsImmutabilityTest extends AbstractOptionSpecOptionsImmutabilityTestCase { + @Override + protected AbstractOptionSpec<?> newOptionSpec( String option ) { + return new NoArgumentOptionSpec( option ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/NoArgumentOptionSpecTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/NoArgumentOptionSpecTest.java new file mode 100644 index 0000000000..e128308c2d --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/NoArgumentOptionSpecTest.java @@ -0,0 +1,53 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Arrays.*; + +import org.junit.Test; + +import static org.infinitest.toolkit.CollectionMatchers.*; +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class NoArgumentOptionSpecTest extends AbstractOptionSpecFixture { + @Override + protected NoArgumentOptionSpec createEqualOptionSpecInstance() { + return new NoArgumentOptionSpec( "a" ); + } + + @Override + protected NoArgumentOptionSpec createNotEqualOptionSpecInstance() { + return new NoArgumentOptionSpec( "b" ); + } + + @Test + public void optionsContents() { + assertThat( createNotEqualOptionSpecInstance().options(), hasSameContentsAs( asList( "b" ) ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/NoArgumentOptionSpecValuesImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/NoArgumentOptionSpecValuesImmutabilityTest.java new file mode 100644 index 0000000000..c2212b3213 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/NoArgumentOptionSpecValuesImmutabilityTest.java @@ -0,0 +1,56 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class NoArgumentOptionSpecValuesImmutabilityTest extends AbstractOptionSpecValuesImmutabilityTestCase<Void> { + @Override + protected AbstractOptionSpec<Void> newOptionSpec() { + return new NoArgumentOptionSpec( "verbose" ); + } + + @Override + protected String firstArg() { + return "1"; + } + + @Override + protected String secondArg() { + return "2"; + } + + @Override + protected Void newItem() { + return null; + } + + @Override + protected Void containedItem() { + return null; + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/NonOptionArgumentSpecTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/NonOptionArgumentSpecTest.java new file mode 100644 index 0000000000..feef72758c --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/NonOptionArgumentSpecTest.java @@ -0,0 +1,108 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import org.junit.Test; + +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.*; + +import static java.util.Arrays.*; +import static java.util.Collections.*; +import static joptsimple.util.DateConverter.*; +import static org.junit.Assert.*; + +public class NonOptionArgumentSpecTest extends AbstractOptionParserFixture { + @Test + public void allowsTypingOfNonOptionArguments() { + OptionSpec<File> nonOptions = parser.nonOptions().ofType( File.class ); + + OptionSet options = parser.parse( "/opt", "/var" ); + + assertEquals( asList( new File( "/opt" ), new File( "/var" ) ), nonOptions.values( options ) ); + } + + @Test + public void allowsDescriptionOfNonOptionArguments() { + OptionSpec<String> nonOptions = parser.nonOptions( "directories" ); + + OptionSet options = parser.parse( "/opt", "/var" ); + + assertEquals( asList( "/opt", "/var" ), nonOptions.values( options ) ); + } + + @Test + public void allowsTypeAndDescriptionOfNonOptionArguments() { + OptionSpec<File> nonOptions = parser.nonOptions( "directories" ).ofType( File.class ); + + OptionSet options = parser.parse( "/opt", "/var" ); + + assertEquals( asList( new File( "/opt" ), new File( "/var" ) ), nonOptions.values( options ) ); + } + + @Test + public void allowsArgumentDescriptionForNonOptionArguments() { + OptionSpec<String> nonOptions = parser.nonOptions().describedAs( "dirs" ); + + OptionSet options = parser.parse( "/opt", "/var" ); + + assertEquals( asList( "/opt", "/var" ), nonOptions.values( options ) ); + } + + @Test + public void doesNotAcceptArguments() { + OptionDescriptor nonOptions = parser.nonOptions().describedAs( "dirs" ); + + assertFalse( nonOptions.acceptsArguments() ); + } + + @Test + public void convertingUsingConverter() throws Exception { + OptionSpec<Date> date = parser.nonOptions().withValuesConvertedBy( datePattern( "MM/dd/yyyy" ) ); + + OptionSet options = parser.parse( "01/24/2013" ); + + assertEquals( + singletonList( new SimpleDateFormat( "MM/dd/yyyy" ).parse( "01/24/2013" ) ), + date.values( options ) ); + } + + @Test( expected = NullPointerException.class ) + public void convertingUsingNullConverter() { + parser.nonOptions().withValuesConvertedBy( null ); + } + + @Test + public void noSpecsCorrespondingToNonOptions() { + OptionParser parser = new OptionParser(); + parser.nonOptions(); + + OptionSet options = parser.parse( "one", "two" ); + + assertEquals( emptyList(), options.specs() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionExceptionLocalizedMessageTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionExceptionLocalizedMessageTest.java new file mode 100644 index 0000000000..e4cd337a2e --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionExceptionLocalizedMessageTest.java @@ -0,0 +1,84 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Locale; + +import static java.util.Arrays.*; +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +@RunWith( Parameterized.class ) +public class OptionExceptionLocalizedMessageTest { + private final OptionException subject; + private final String expectedMessage; + + public OptionExceptionLocalizedMessageTest( OptionException subject, String expectedMessage ) { + this.subject = subject; + this.expectedMessage = expectedMessage; + } + + @Parameterized.Parameters + public static Collection<?> exceptionsAndMessages() { + return asList( + new Object[] { new IllegalOptionSpecificationException( "," ), "illegal option specification exception" }, + new Object[] { new MultipleArgumentsForOptionException( + new RequiredArgumentOptionSpec<>( asList( "b", "c" ), "d" ) ), + "multiple arguments for option exception" }, + new Object[] { new OptionArgumentConversionException( + new RequiredArgumentOptionSpec<>( asList( "c", "number" ), "x" ), "d", null ), + "option argument conversion exception" }, + new Object[] { new OptionMissingRequiredArgumentException( + new RequiredArgumentOptionSpec<>( asList( "e", "honest" ), "" ) ), + "option missing required argument exception" }, + new Object[] { new UnrecognizedOptionException( "f" ), "unrecognized option exception" }, + new Object[] { new MissingRequiredOptionsException( + Arrays.<AbstractOptionSpec<?>> asList( + new NoArgumentOptionSpec( "g" ), new NoArgumentOptionSpec( "h" ) ) ), + "missing required option exception" }, + new Object[] { new MissingRequiredOptionsException( + Arrays.<AbstractOptionSpec<?>> asList( + new RequiredArgumentOptionSpec<>( asList( "p", "place" ), "spot" ), + new RequiredArgumentOptionSpec<>( asList( "d", "data-dir" ), "dir" ) ) ), + "missing required option exception" }, + new Object[] { new UnconfiguredOptionException( asList( "i", "j" ) ), + "unconfigured option exception" } + ); + } + + @Test + public void givesCorrectExceptionMessage() { + assertEquals( expectedMessage, subject.localizedMessage( new Locale( "xx", "YY" ) ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionExceptionMessageTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionExceptionMessageTest.java new file mode 100644 index 0000000000..3afdd8350f --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionExceptionMessageTest.java @@ -0,0 +1,91 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.Arrays; +import java.util.Collection; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import static com.google.common.collect.Lists.newArrayList; +import static java.util.Arrays.*; +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +@RunWith( Parameterized.class ) +public class OptionExceptionMessageTest { + private final OptionException subject; + private final String expectedMessage; + + public OptionExceptionMessageTest( OptionException subject, String expectedMessage ) { + this.subject = subject; + this.expectedMessage = expectedMessage; + } + + @Parameterized.Parameters + public static Collection<?> exceptionsAndMessages() { + return asList( + new Object[] { new IllegalOptionSpecificationException( "," ), ", is not a legal option character" }, + new Object[] { new MultipleArgumentsForOptionException( + new RequiredArgumentOptionSpec<>( asList( "b", "c" ), "d" ) ), + "Found multiple arguments for option b/c, but you asked for only one" }, + new Object[] { new OptionArgumentConversionException( + new RequiredArgumentOptionSpec<>( asList( "c", "number" ), "x" ), "d", null ), + "Cannot parse argument 'd' of option c/number" }, + new Object[] { new OptionMissingRequiredArgumentException( + new RequiredArgumentOptionSpec<>( asList( "e", "honest" ), "" ) ), + "Option e/honest requires an argument" }, + new Object[] { new UnrecognizedOptionException( "f" ), "f is not a recognized option" }, + new Object[] { new MissingRequiredOptionsException( + Arrays.<AbstractOptionSpec<?>> asList( + new NoArgumentOptionSpec( "g" ), new NoArgumentOptionSpec( "h" ) ) ), + "Missing required option(s) [g, h]" }, + new Object[] { new MissingRequiredOptionsException( + Arrays.<AbstractOptionSpec<?>> asList( + new RequiredArgumentOptionSpec<>( asList( "p", "place" ), "spot" ), + new RequiredArgumentOptionSpec<>( asList( "d", "data-dir" ), "dir" ) ) ), + "Missing required option(s) [p/place, d/data-dir]" }, + new Object[] { new UnconfiguredOptionException( asList( "i", "j" ) ), + "Option(s) [i, j] not configured on this parser" }, + new Object[] { + new UnavailableOptionException( + newArrayList( new NoArgumentOptionSpec( "a" ), new NoArgumentOptionSpec( "b" ) ) ), + "Option(s) [a, b] are unavailable given other options on the command line" + } + ); + } + + @Test + public void givesCorrectExceptionMessage() { + assertEquals( expectedMessage, subject.getLocalizedMessage() ); + assertEquals( expectedMessage, subject.getMessage() ); + assertEquals( subject.getClass().getName() + ": " + expectedMessage, subject.toString() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionExceptionOptionsImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionExceptionOptionsImmutabilityTest.java new file mode 100644 index 0000000000..465d960cf7 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionExceptionOptionsImmutabilityTest.java @@ -0,0 +1,59 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.List; + +import org.infinitest.toolkit.UnmodifiableListTestSupport; + +import static java.util.Arrays.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class OptionExceptionOptionsImmutabilityTest extends UnmodifiableListTestSupport<String> { + @Override + protected List<String> newList() { + return new OptionException( asList( "a", "b" ) ) { + private static final long serialVersionUID = -1L; + + @Override + Object[] messageArguments() { + return new Object[0]; + } + }.options(); + } + + @Override + protected String newItem() { + return "c"; + } + + @Override + protected String containedItem() { + return "a"; + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserAlternateHelpFormatterTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserAlternateHelpFormatterTest.java new file mode 100644 index 0000000000..b799df696b --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserAlternateHelpFormatterTest.java @@ -0,0 +1,61 @@ +package joptsimple; + +import java.io.StringWriter; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import static java.util.Arrays.*; + +import org.junit.Before; +import org.junit.Test; + +import static org.infinitest.toolkit.CollectionMatchers.*; +import static org.junit.Assert.*; + +public class OptionParserAlternateHelpFormatterTest extends AbstractOptionParserFixture { + private StringWriter sink; + private Map<String, ? extends OptionDescriptor> captured; + + @Before + public void primeParser() throws Exception { + captured = new HashMap<>(); + + parser.accepts( "b", "boo" ); + + parser.formatHelpWith( new HelpFormatter() { + public String format( Map<String, ? extends OptionDescriptor> options ) { + captured = options; + return "some help you are"; + } + } ); + + sink = new StringWriter(); + + parser.printHelpOn( sink ); + } + + @Test + public void asksAlternateFormatterForHelpString() { + assertEquals( "some help you are", sink.toString() ); + } + + @Test + public void getsFedOptionDescriptorsForRecognizedOptions() { + assertEquals( 2, captured.size() ); + Iterator<? extends Map.Entry<String,? extends OptionDescriptor>> iterator = captured.entrySet().iterator(); + Map.Entry<String, ? extends OptionDescriptor> first = iterator.next(); + assertEquals( "[arguments]", first.getKey() ); + Map.Entry<String, ? extends OptionDescriptor> second = iterator.next(); + assertEquals("b", second.getKey()); + OptionDescriptor descriptor = second.getValue(); + assertThat( descriptor.options(), hasSameContentsAs( asList( "b" ) ) ); + assertEquals( "boo", descriptor.description() ); + assertFalse( descriptor.acceptsArguments() ); + assertFalse( descriptor.requiresArgument() ); + assertEquals( "", descriptor.argumentDescription() ); + assertEquals( "", descriptor.argumentTypeIndicator() ); + assertEquals( Collections.emptyList(), descriptor.defaultValues() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserArgumentExceptionTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserArgumentExceptionTest.java new file mode 100644 index 0000000000..4661795a74 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserArgumentExceptionTest.java @@ -0,0 +1,82 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.Collections; + +import static java.util.Collections.*; + +import org.junit.Test; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class OptionParserArgumentExceptionTest extends AbstractOptionParserFixture { + @Test( expected = NullPointerException.class ) + public void createWithNullOptionSpec() { + new OptionParser( null ); + } + + @Test( expected = NullPointerException.class ) + public void parseNull() { + parser.parse( (String[]) null ); + } + + @Test( expected = NullPointerException.class ) + public void nullOptionToAccepts() { + parser.accepts( null ); + } + + @Test( expected = NullPointerException.class ) + public void nullOptionToAcceptsWithDescription() { + parser.accepts( null, "a weird option" ); + } + + @Test( expected = NullPointerException.class ) + public void nullOptionListToAcceptsAll() { + parser.acceptsAll( null ); + } + + @Test( expected = IllegalArgumentException.class ) + public void emptyOptionListToAcceptsAll() { + parser.acceptsAll( Collections.<String> emptyList() ); + } + + @Test( expected = NullPointerException.class ) + public void optionListContainingNullToAcceptsAll() { + parser.acceptsAll( singletonList( (String) null ) ); + } + + @Test( expected = NullPointerException.class ) + public void nullOptionListToAcceptsAllWithDescription() { + parser.acceptsAll( null, "some weird options" ); + } + + @Test( expected = NullPointerException.class ) + public void optionListContainingNullToAcceptsAllWithDescription() { + parser.acceptsAll( singletonList( (String) null ), "some weird options" ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserNewDeclarationTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserNewDeclarationTest.java new file mode 100644 index 0000000000..0381af24d4 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserNewDeclarationTest.java @@ -0,0 +1,290 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.math.BigInteger; +import java.sql.Time; +import java.sql.Timestamp; + +import static java.lang.Boolean.*; +import static java.util.Arrays.*; +import static java.util.Collections.*; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class OptionParserNewDeclarationTest extends AbstractOptionParserFixture { + @Test( expected = IllegalOptionSpecificationException.class ) + public void acceptsIllegalCharacters() { + parser.accepts( "!" ); + } + + @Test + public void booleanArgumentType() { + parser.accepts( "a" ).withRequiredArg().ofType( Boolean.class ); + parser.accepts( "b" ).withOptionalArg().ofType( Boolean.class ); + + OptionSet options = parser.parse( "-a", "true", "-b", "false" ); + + assertOptionDetected( options, "a" ); + assertOptionDetected( options, "b" ); + assertEquals( TRUE, options.valueOf( "a" ) ); + assertEquals( singletonList( TRUE ), options.valuesOf( "a" ) ); + assertEquals( FALSE, options.valueOf( "b" ) ); + assertEquals( singletonList( FALSE ), options.valuesOf( "b" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void byteArgumentType() { + parser.accepts( "a" ).withRequiredArg().ofType( Byte.class ); + parser.accepts( "b" ).withOptionalArg().ofType( Byte.class ); + + OptionSet options = parser.parse( "-a", "-1", "-b", "-2" ); + + assertOptionDetected( options, "a" ); + assertOptionDetected( options, "b" ); + assertEquals( Byte.valueOf( "-1" ), options.valueOf( "a" ) ); + assertEquals( singletonList( Byte.valueOf( "-1" ) ), options.valuesOf( "a" ) ); + assertEquals( Byte.valueOf( "-2" ), options.valueOf( "b" ) ); + assertEquals( singletonList( Byte.valueOf( "-2" ) ), options.valuesOf( "b" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void doubleArgumentType() { + parser.accepts( "a" ).withRequiredArg().ofType( Double.class ); + parser.accepts( "b" ).withOptionalArg().ofType( Double.class ); + + OptionSet options = parser.parse( "-a", "3.1415926D", "-b", "6.02E23" ); + + assertOptionDetected( options, "a" ); + assertOptionDetected( options, "b" ); + assertEquals( Double.valueOf( "3.1415926D" ), options.valueOf( "a" ) ); + assertEquals( asList( Double.valueOf( "3.1415926D" ) ), options.valuesOf( "a" ) ); + assertEquals( Double.valueOf( "6.02E23" ), options.valueOf( "b" ) ); + assertEquals( asList( Double.valueOf( "6.02E23" ) ), options.valuesOf( "b" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void floatArgumentType() { + parser.accepts( "a" ).withRequiredArg().ofType( Float.class ); + parser.accepts( "b" ).withOptionalArg().ofType( Float.class ); + + OptionSet options = parser.parse( "-a", "3.1415926F", "-b", "6.02E23F" ); + + assertOptionDetected( options, "a" ); + assertOptionDetected( options, "b" ); + assertEquals( Float.valueOf( "3.1415926F" ), options.valueOf( "a" ) ); + assertEquals( asList( Float.valueOf( "3.1415926F" ) ), options.valuesOf( "a" ) ); + assertEquals( Float.valueOf( "6.02E23F" ), options.valueOf( "b" ) ); + assertEquals( asList( Float.valueOf( "6.02E23F" ) ), options.valuesOf( "b" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void integerArgumentType() { + parser.accepts( "a" ).withRequiredArg().ofType( Integer.class ); + parser.accepts( "b" ).withOptionalArg().ofType( Integer.class ); + + OptionSet options = parser.parse( "-a", "12", "-b", "34" ); + + assertOptionDetected( options, "a" ); + assertOptionDetected( options, "b" ); + assertEquals( Integer.valueOf( "12" ), options.valueOf( "a" ) ); + assertEquals( asList( Integer.valueOf( "12" ) ), options.valuesOf( "a" ) ); + assertEquals( Integer.valueOf( "34" ), options.valueOf( "b" ) ); + assertEquals( asList( Integer.valueOf( "34" ) ), options.valuesOf( "b" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void longArgumentType() { + parser.accepts( "a" ).withRequiredArg().ofType( Long.class ); + parser.accepts( "b" ).withOptionalArg().ofType( Long.class ); + + OptionSet options = parser.parse( "-a", "123454678901234", "-b", "98765432109876" ); + + assertOptionDetected( options, "a" ); + assertOptionDetected( options, "b" ); + assertEquals( Long.valueOf( "123454678901234" ), options.valueOf( "a" ) ); + assertEquals( singletonList( Long.valueOf( "123454678901234" ) ), options.valuesOf( "a" ) ); + assertEquals( Long.valueOf( "98765432109876" ), options.valueOf( "b" ) ); + assertEquals( singletonList( Long.valueOf( "98765432109876" ) ), options.valuesOf( "b" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void shortArgumentType() { + parser.accepts( "a" ).withRequiredArg().ofType( Short.class ); + parser.accepts( "b" ).withOptionalArg().ofType( Short.class ); + + OptionSet options = parser.parse( "-a", "5675", "-b", "345" ); + + assertOptionDetected( options, "a" ); + assertOptionDetected( options, "b" ); + assertEquals( Short.valueOf( "5675" ), options.valueOf( "a" ) ); + assertEquals( asList( Short.valueOf( "5675" ) ), options.valuesOf( "a" ) ); + assertEquals( Short.valueOf( "345" ), options.valueOf( "b" ) ); + assertEquals( asList( Short.valueOf( "345" ) ), options.valuesOf( "b" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void sqlDateArgumentType() { + parser.accepts( "a" ).withRequiredArg().ofType( java.sql.Date.class ); + parser.accepts( "b" ).withOptionalArg().ofType( java.sql.Date.class ); + + OptionSet options = parser.parse( "-a", "2001-09-11", "-b", "1941-12-07" ); + + assertOptionDetected( options, "a" ); + assertOptionDetected( options, "b" ); + assertEquals( java.sql.Date.valueOf( "2001-09-11" ), options.valueOf( "a" ) ); + assertEquals( singletonList( java.sql.Date.valueOf( "2001-09-11" ) ), options.valuesOf( "a" ) ); + assertEquals( java.sql.Date.valueOf( "1941-12-07" ), options.valueOf( "b" ) ); + assertEquals( singletonList( java.sql.Date.valueOf( "1941-12-07" ) ), options.valuesOf( "b" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void sqlTimeArgumentType() { + parser.accepts( "a" ).withRequiredArg().ofType( Time.class ); + parser.accepts( "b" ).withOptionalArg().ofType( Time.class ); + + OptionSet options = parser.parse( "-a", "08:57:39", "-b", "23:59:59" ); + + assertOptionDetected( options, "a" ); + assertOptionDetected( options, "b" ); + assertEquals( Time.valueOf( "08:57:39" ), options.valueOf( "a" ) ); + assertEquals( asList( Time.valueOf( "08:57:39" ) ), options.valuesOf( "a" ) ); + assertEquals( Time.valueOf( "23:59:59" ), options.valueOf( "b" ) ); + assertEquals( asList( Time.valueOf( "23:59:59" ) ), options.valuesOf( "b" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void sqlTimestampArgumentType() { + parser.accepts( "a" ).withRequiredArg().ofType( Timestamp.class ); + parser.accepts( "b" ).withOptionalArg().ofType( Timestamp.class ); + + OptionSet options = parser.parse( "-a", "1970-01-01 00:00:00", "-b", "1979-12-31 23:59:59.0123456" ); + + assertOptionDetected( options, "a" ); + assertOptionDetected( options, "b" ); + assertEquals( Timestamp.valueOf( "1970-01-01 00:00:00" ), options.valueOf( "a" ) ); + assertEquals( singletonList( Timestamp.valueOf( "1970-01-01 00:00:00" ) ), options.valuesOf( "a" ) ); + assertEquals( Timestamp.valueOf( "1979-12-31 23:59:59.0123456" ), options.valueOf( "b" ) ); + assertEquals( singletonList( Timestamp.valueOf( "1979-12-31 23:59:59.0123456" ) ), options.valuesOf( "b" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test( expected = OptionException.class ) + public void illegalOptionArgumentMethodConversion() { + parser.accepts( "a" ).withRequiredArg().ofType( Integer.class ); + + OptionSet options = parser.parse( "-a", "foo" ); + + options.valueOf( "a" ); + } + + @Test( expected = OptionException.class ) + public void illegalOptionArgumentConstructorConversion() { + parser.accepts( "a" ).withRequiredArg().ofType( BigInteger.class ); + + OptionSet options = parser.parse( "-a", "foo" ); + + options.valueOf( "a" ); + } + + @Test + public void optionsWithOptionalNegativeNumberArguments() { + parser.accepts( "a" ).withOptionalArg().ofType( Integer.class ); + parser.accepts( "b" ).withOptionalArg().ofType( Integer.class ); + parser.accepts( "1" ); + parser.accepts( "2" ); + + OptionSet options = parser.parse( "-a", "-1", "-b", "-2" ); + + assertOptionDetected( options, "a" ); + assertOptionDetected( options, "b" ); + assertEquals( Integer.valueOf( "-1" ), options.valueOf( "a" ) ); + assertEquals( asList( Integer.valueOf( "-1" ) ), options.valuesOf( "a" ) ); + assertEquals( Integer.valueOf( "-2" ), options.valueOf( "b" ) ); + assertEquals( asList( Integer.valueOf( "-2" ) ), options.valuesOf( "b" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void optionsWithOptionalNegativeNumberArgumentsAndNumberOptions() { + parser.accepts( "a" ).withOptionalArg().ofType( Integer.class ); + parser.accepts( "b" ).withOptionalArg().ofType( Integer.class ); + parser.accepts( "1" ); + parser.accepts( "2" ); + + OptionSet options = parser.parse( "-1", "-2", "-a", "-b" ); + + assertOptionDetected( options, "1" ); + assertOptionDetected( options, "a" ); + assertOptionDetected( options, "2" ); + assertOptionDetected( options, "b" ); + assertNull( options.valueOf( "1" ) ); + assertNull( options.valueOf( "a" ) ); + assertNull( options.valueOf( "2" ) ); + assertNull( options.valueOf( "b" ) ); + assertEquals( emptyList(), options.valuesOf( "1" ) ); + assertEquals( emptyList(), options.valuesOf( "a" ) ); + assertEquals( emptyList(), options.valuesOf( "2" ) ); + assertEquals( emptyList(), options.valuesOf( "b" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void optionsWithNegativeNumberArgumentsAndNonNumberOptions() { + parser.accepts( "a" ).withOptionalArg().ofType( Integer.class ); + parser.accepts( "b" ).withOptionalArg().ofType( Integer.class ); + parser.accepts( "1" ); + parser.accepts( "2" ); + + OptionSet options = parser.parse( "-1", "-a", "-b", "-2" ); + + assertOptionDetected( options, "1" ); + assertOptionDetected( options, "a" ); + assertOptionDetected( options, "b" ); + assertOptionNotDetected( options, "2" ); + assertNull( options.valueOf( "1" ) ); + assertNull( options.valueOf( "a" ) ); + assertEquals( Integer.valueOf( "-2" ), options.valueOf( "b" ) ); + assertEquals( emptyList(), options.valuesOf( "1" ) ); + assertEquals( emptyList(), options.valuesOf( "a" ) ); + assertEquals( asList( Integer.valueOf( "-2" ) ), options.valuesOf( "b" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserOptionExceptionTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserOptionExceptionTest.java new file mode 100644 index 0000000000..3e219d5207 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserOptionExceptionTest.java @@ -0,0 +1,78 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import org.junit.Test; + +import static joptsimple.ExceptionMatchers.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class OptionParserOptionExceptionTest extends AbstractOptionParserFixture { + @Test + public void unrecognizedOption() { + thrown.expect( UnrecognizedOptionException.class ); + thrown.expect( withOption( "a" ) ); + + parser.parse( "-a" ); + } + + @Test + public void illegalOptionCharacter() { + thrown.expect( IllegalOptionSpecificationException.class ); + thrown.expect( withOption( "%" ) ); + + parser.accepts( "%" ); + } + + @Test + public void asteriskIsIllegalOptionCharacter() { + thrown.expect( IllegalOptionSpecificationException.class ); + thrown.expect( withOption( "*" ) ); + + parser.accepts( "*" ); + } + + @Test + public void tooManyHyphens() { + parser.accepts( "b" ); + thrown.expect( UnrecognizedOptionException.class ); + thrown.expect( withOption( "-b" ) ); + + parser.parse( "---b" ); + } + + @Test + public void valueOfWhenMultiples() { + parser.accepts( "e" ).withRequiredArg(); + OptionSet options = parser.parse( "-e", "foo", "-e", "bar" ); + thrown.expect( MultipleArgumentsForOptionException.class ); + thrown.expect( withOption( "e" ) ); + + options.valueOf( "e" ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserRecognizedOptionsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserRecognizedOptionsTest.java new file mode 100644 index 0000000000..3bddfb998b --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserRecognizedOptionsTest.java @@ -0,0 +1,67 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package joptsimple; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Map; + +import static java.util.Arrays.asList; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +public class OptionParserRecognizedOptionsTest extends AbstractOptionParserFixture { + @Test + public void basicOptionsRecognized() { + parser.accepts( "first" ).withRequiredArg().required(); + parser.accepts( "second" ).withOptionalArg(); + parser.accepts( "third" ).forHelp(); + + Map<String, OptionSpec<?>> recognizedOptions = parser.recognizedOptions(); + + assertEquals( 4, recognizedOptions.size() ); + assertTrue( recognizedOptions.keySet().contains( "first" ) ); + assertTrue( recognizedOptions.keySet().contains( "second" ) ); + assertTrue( recognizedOptions.keySet().contains( "third" ) ); + assertTrue( recognizedOptions.keySet().contains( "[arguments]" ) ); + assertTrue( recognizedOptions.get( "third" ).isForHelp() ); + assertFalse( recognizedOptions.get( "second" ).isForHelp() ); + assertNotNull( recognizedOptions.get( "first" ).options() ); + } + + @Test + public void parserPreservesTrainingOrder() { + final OptionSpecBuilder z = parser.acceptsAll( asList( "zebra", "aardvark" ) ); + final OptionSpecBuilder y = parser.accepts( "yak" ); + final OptionSpecBuilder x = parser.acceptsAll( asList( "baboon", "xantus" ) ); + + assertEquals( asList( "[arguments]", "aardvark", "zebra", "yak", "baboon", "xantus" ), new ArrayList<String>( + parser.recognizedOptions().keySet() ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserTest.java new file mode 100644 index 0000000000..5538f2d171 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserTest.java @@ -0,0 +1,318 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.lang.Boolean.*; +import static java.util.Arrays.*; +import static java.util.Collections.*; + +import org.hamcrest.Description; +import org.hamcrest.TypeSafeMatcher; +import org.junit.Test; + +import static joptsimple.ExceptionMatchers.*; +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class OptionParserTest extends AbstractOptionParserFixture { + @Test + public void optionsAndNonOptionsInterspersed() { + parser.accepts( "i" ).withOptionalArg(); + parser.accepts( "j" ).withOptionalArg(); + parser.accepts( "k" ); + + OptionSet options = + parser.parse( "-ibar", "-i", "junk", "xyz", "-jixnay", "foo", "-k", "blah", "--", "yermom" ); + + assertOptionDetected( options, "i" ); + assertOptionDetected( options, "j" ); + assertOptionDetected( options, "k" ); + assertEquals( asList( "bar", "junk" ), options.valuesOf( "i" ) ); + assertEquals( singletonList( "ixnay" ), options.valuesOf( "j" ) ); + assertEquals( emptyList(), options.valuesOf( "k" ) ); + assertEquals( asList( "xyz", "foo", "blah", "yermom" ), options.nonOptionArguments() ); + } + + @Test + public void shortOptionSpecifiedAsLongOptionWithoutArgument() { + parser.accepts( "x" ); + + OptionSet options = parser.parse( "--x" ); + assertOptionDetected( options, "x" ); + assertEquals( emptyList(), options.valuesOf( "x" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void longOptionLeadsWithSingleDash() { + parser.accepts( "quiet" ); + parser.accepts( "queen" ); + + OptionSet options = parser.parse( "-quiet" ); + assertOptionDetected( options, "quiet" ); + assertEquals( emptyList(), options.valuesOf( "quiet" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void parsesLongOptionAsAbbreviatedShortOption() { + parser.accepts( "queen" ); + + parser.parse( "-que" ); + } + + @Test + public void parsesLongOptionAsAbbreviatedLongOption() { + parser.accepts( "queen" ); + + parser.parse( "--que" ); + } + + @Test + public void longOptionLeadsWithSingleDashAmbiguous() { + parser.accepts( "quiet" ); + parser.accepts( "queen" ); + thrown.expect( UnrecognizedOptionException.class ); + thrown.expect( withOption( "q" ) ); + + parser.parse( "-q" ); + } + + @Test + public void longOptionLeadsWithSingleDashAmbiguousButShortsAreLegal() { + parser.accepts( "quiet" ); + parser.accepts( "queen" ); + parser.accepts( "q" ); + parser.accepts( "u" ); + + OptionSet options = parser.parse( "-qu" ); + assertOptionDetected( options, "q" ); + assertOptionDetected( options, "u" ); + assertOptionNotDetected( options, "quiet" ); + assertOptionNotDetected( options, "queen" ); + assertEquals( emptyList(), options.valuesOf( "q" ) ); + assertEquals( emptyList(), options.valuesOf( "u" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void longOptionLeadsWithSingleDashAmbiguousButAShortIsIllegal() { + parser.accepts( "quiet" ); + parser.accepts( "queen" ); + parser.accepts( "q" ); + thrown.expect( UnrecognizedOptionException.class ); + thrown.expect( withOption( "u" ) ); + + parser.parse( "-qu" ); + } + + @Test + public void longOptionLeadsWithSingleDashAmbiguousButAShortAcceptsAnArgument() { + parser.accepts( "quiet" ); + parser.accepts( "queen" ); + parser.accepts( "q" ).withOptionalArg(); + + OptionSet options = parser.parse( "-qu" ); + assertOptionDetected( options, "q" ); + assertOptionNotDetected( options, "quiet" ); + assertOptionNotDetected( options, "queen" ); + assertEquals( singletonList( "u" ), options.valuesOf( "q" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void resetHappensAfterParsing() { + parser.accepts( "i" ).withOptionalArg(); + parser.accepts( "j" ).withOptionalArg(); + parser.accepts( "k" ); + + String[] args = { "-ibar", "-i", "junk", "xyz", "-jixnay", "foo", "-k", "blah", "--", "yermom" }; + + OptionSet options = parser.parse( args ); + assertEquals( options, parser.parse( args ) ); + } + + @Test + public void typedArguments() { + parser.accepts( "a" ).withRequiredArg().ofType( Boolean.class ); + parser.accepts( "b" ).withOptionalArg().ofType( Integer.class ); + + OptionSet options = parser.parse( "-a", "false", "-b", "3", "extra" ); + + assertOptionDetected( options, "a" ); + assertOptionDetected( options, "b" ); + assertEquals( FALSE, options.valueOf( "a" ) ); + assertEquals( singletonList( FALSE ), options.valuesOf( "a" ) ); + assertEquals( Integer.valueOf( "3" ), options.valueOf( "b" ) ); + assertEquals( singletonList( Integer.valueOf( "3" ) ), options.valuesOf( "b" ) ); + assertEquals( singletonList( "extra" ), options.nonOptionArguments() ); + } + + @Test + public void allowsMixingOfOptionsAndNonOptions() { + parser.accepts( "i" ).withRequiredArg(); + parser.accepts( "j" ).withOptionalArg(); + parser.accepts( "k" ); + + OptionSet options = parser.parse( "a", "b", "c", "-i", "boo", "d", "e", "-k", "f", "-j" ); + + assertOptionDetected( options, "i" ); + assertEquals( singletonList( "boo" ), options.valuesOf( "i" ) ); + assertOptionDetected( options, "j" ); + assertEquals( emptyList(), options.valuesOf( "j" ) ); + assertOptionDetected( options, "k" ); + assertEquals( emptyList(), options.valuesOf( "k" ) ); + assertEquals( asList( "a", "b", "c", "d", "e", "f" ), options.nonOptionArguments() ); + } + + @Test + public void disallowsMixingOfOptionsAndNonOptionsUnderPosixlyCorrect() { + parser.accepts( "i" ).withRequiredArg(); + parser.accepts( "j" ).withOptionalArg(); + parser.accepts( "k" ); + parser.posixlyCorrect( true ); + + OptionSet options = parser.parse( "a", "b", "c", "-i", "boo", "d", "e", "-k", "f", "-j" ); + + assertOptionNotDetected( options, "i" ); + assertEquals( emptyList(), options.valuesOf( "i" ) ); + assertOptionNotDetected( options, "j" ); + assertEquals( emptyList(), options.valuesOf( "j" ) ); + assertOptionNotDetected( options, "k" ); + assertEquals( emptyList(), options.valuesOf( "j" ) ); + assertEquals( asList( "a", "b", "c", "-i", "boo", "d", "e", "-k", "f", "-j" ), options.nonOptionArguments() ); + } + + @Test + public void doubleHyphenSignalsEndsOfOptions() { + OptionSet options = new OptionParser( "ab:c::de:f::" ) { + { + accepts( "verbose" ); + } + }.parse( "-a", "-b=foo", "-c=bar", "--", "-d", "-verbose", "-e", "baz", "-f", "biz" ); + + assertOptionDetected( options, "a" ); + assertEquals( emptyList(), options.valuesOf( "a" ) ); + assertOptionDetected( options, "b" ); + assertEquals( singletonList( "foo" ), options.valuesOf( "b" ) ); + assertOptionDetected( options, "c" ); + assertEquals( singletonList( "bar" ), options.valuesOf( "c" ) ); + assertOptionNotDetected( options, "d" ); + assertOptionNotDetected( options, "verbose" ); + assertOptionNotDetected( options, "e" ); + assertOptionNotDetected( options, "f" ); + assertEquals( asList( "-d", "-verbose", "-e", "baz", "-f", "biz" ), options.nonOptionArguments() ); + } + + @Test + public void allowsEmptyStringAsArgumentOfOption() { + OptionSpec<String> optionI = parser.accepts( "i" ).withOptionalArg(); + + OptionSet options = parser.parse( "-i", "" ); + + assertOptionDetected( options, "i" ); + assertEquals( "", optionI.value( options ) ); + } + + @Test + public void allowsWhitespaceyStringAsArgumentOfOption() { + String whitespace = " \t\t\n\n\f\f \r\r "; + OptionSpec<String> optionJ = parser.accepts( "j" ).withRequiredArg(); + + OptionSet options = parser.parse( "-j", whitespace ); + + assertOptionDetected( options, "j" ); + assertEquals( whitespace, optionJ.value( options ) ); + } + + @Test + public void allowsEmbeddedWhitespaceInArgumentOfOption() { + String withEmbeddedWhitespace = " look at me, I'm flaunting the rules! "; + OptionSpec<String> optionJ = parser.accepts( "j" ).withRequiredArg(); + + OptionSet options = parser.parse( "-j", withEmbeddedWhitespace ); + + assertOptionDetected( options, "j" ); + assertEquals( withEmbeddedWhitespace, optionJ.value( options ) ); + } + + @Test + public void requiredOptionWithArgMissing() { + parser.accepts( "t" ).withOptionalArg().required(); + thrown.expect( MissingRequiredOptionsException.class ); + thrown.expect( withOption( "t" ) ); + + parser.parse(); + } + + @Test + public void requiredOptionButHelpOptionPresent() { + parser.accepts( "t" ).withOptionalArg().required(); + parser.accepts( "h" ).forHelp(); + + parser.parse( "-h" ); + } + + @Test + public void configurationPerformedLaterOverrideThosePerformedEarlierForTheSameOption() { + parser.accepts( "t" ).withRequiredArg(); + parser.accepts( "t" ).withOptionalArg(); + + parser.parse( "-t" ); + } + + @Test + public void requiredOptionWithSynonymsMissing() { + parser.acceptsAll( asList( "h", "help", "?" ) ); + parser.acceptsAll( asList( "f", "ff", "csv-file-name" ) ).withRequiredArg().required(); + + thrown.expect( MissingRequiredOptionsException.class ); + thrown.expectMessage( new TypeSafeMatcher<String>() { + @Override + protected boolean matchesSafely( String item ) { + return "Missing required option(s) [f/csv-file-name/ff]".equals( item ); + } + + public void describeTo(Description description) { + // purposely doing nothing here + } + } ); + + parser.parse(); + } + + @Test + public void abbreviationsCanBeDisallowed() { + OptionParser parser = new OptionParser(false); + parser.accepts( "abbreviatable" ); + + thrown.expect( UnrecognizedOptionException.class ); + + parser.parse( "--abb" ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserUnrecognizedOptionsAllowedTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserUnrecognizedOptionsAllowedTest.java new file mode 100644 index 0000000000..8df74cacb2 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionParserUnrecognizedOptionsAllowedTest.java @@ -0,0 +1,54 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static joptsimple.ExceptionMatchers.withOption; +import static java.util.Arrays.asList; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class OptionParserUnrecognizedOptionsAllowedTest extends AbstractOptionParserFixture { + @Test + public void unrecognizedOptionDisallowed() { + assertFalse( parser.doesAllowsUnrecognizedOptions() ); + + thrown.expect( UnrecognizedOptionException.class ); + thrown.expect( withOption( "a" ) ); + + parser.parse( "-a" ); + } + + @Test + public void unrecognizedOptionAllowed() { + parser.allowsUnrecognizedOptions(); + + OptionSet options = parser.parse( "-a" ); + + assertEquals( asList( "-a" ), options.nonOptionArguments() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetAsMapTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetAsMapTest.java new file mode 100644 index 0000000000..0a8c9a67d6 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetAsMapTest.java @@ -0,0 +1,49 @@ +package joptsimple; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static java.util.Arrays.asList; +import static java.util.Collections.*; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +/** + * @author <a href="mailto:binkley@alumni.rice.edu">B. K. Oxley (binkley)</a> + */ +public class OptionSetAsMapTest extends AbstractOptionParserFixture { + @Test + public void gives() { + final OptionSpec<Void> a = parser.accepts( "a" ); + final OptionSpec<String> b = parser.accepts( "b" ).withRequiredArg(); + final OptionSpec<String> c = parser.accepts( "c" ).withOptionalArg(); + final OptionSpec<String> d = parser.accepts( "d" ).withRequiredArg().defaultsTo( "1" ); + final OptionSpec<String> e = parser.accepts( "e" ).withOptionalArg().defaultsTo( "2" ); + final OptionSpec<String> f = parser.accepts( "f" ).withRequiredArg().defaultsTo( "3" ); + final OptionSpec<String> g = parser.accepts( "g" ).withOptionalArg().defaultsTo( "4" ); + final OptionSpec<Void> h = parser.accepts( "h" ); + + OptionSet options = parser.parse( "-a", "-e", "-c", "5", "-d", "6", "-b", "4", "-d", "7", "-e", "8" ); + + Map<OptionSpec<?>, List<?>> expected = new HashMap<OptionSpec<?>, List<?>>() { + private static final long serialVersionUID = Long.MIN_VALUE; + + { + put( a, emptyList() ); + put( b, asList( "4" ) ); + put( c, asList( "5" ) ); + put( d, asList( "6", "7" ) ); + put( e, asList( "8" ) ); + put( f, asList( "3" ) ); + put( g, asList( "4" ) ); + put( h, emptyList() ); + } + }; + + assertThat( options.asMap(), is( equalTo( expected ) ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetDetectedOptionsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetDetectedOptionsTest.java new file mode 100644 index 0000000000..3a7766472e --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetDetectedOptionsTest.java @@ -0,0 +1,50 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.Arrays; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class OptionSetDetectedOptionsTest extends AbstractOptionParserFixture { + @Test + public void givesSpecsInOrderOfCommandLinePresentation() { + OptionSpec<Void> a = parser.accepts( "a" ); + OptionSpec<String> b = parser.accepts( "b" ).withRequiredArg(); + OptionSpec<String> c = parser.accepts( "c" ).withOptionalArg(); + OptionSpec<String> d = parser.accepts( "d" ).withRequiredArg().defaultsTo( "1" ); + OptionSpec<String> e = parser.accepts( "e" ).withOptionalArg().defaultsTo( "2" ); + + OptionSet options = parser.parse( "-a", "-e", "-c", "5", "-d", "6", "-b", "4", "-d", "7", "-e", "8" ); + + assertEquals( Arrays.asList( a, e, c, d, b, d, e ), options.specs() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetEqualsHashCodeTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetEqualsHashCodeTest.java new file mode 100644 index 0000000000..28757ff0c8 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetEqualsHashCodeTest.java @@ -0,0 +1,59 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.Collections; + +import org.infinitest.toolkit.StrictEqualsHashCodeTestSupport; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class OptionSetEqualsHashCodeTest extends StrictEqualsHashCodeTestSupport { + @Override + protected OptionSet equal() { + OptionSet options = new OptionSet( Collections.<String, AbstractOptionSpec<?>> emptyMap() ); + options.addWithArgument( new RequiredArgumentOptionSpec<String>( "anOption" ), "anArg" ); + return options; + } + + @Override + protected OptionSet notEqual() { + OptionSet options = new OptionSet( Collections.<String, AbstractOptionSpec<?>> emptyMap() ); + options.addWithArgument( new RequiredArgumentOptionSpec<String>( "anOption" ), "aDifferentArg" ); + return options; + } + + @Override + protected Object equalButDifferentClass() { + OptionSet options = + new OptionSet( Collections.<String, AbstractOptionSpec<?>> emptyMap() ) { + // anonymous subclass + }; + options.addWithArgument( new RequiredArgumentOptionSpec<String>( "anOption" ), "anArg" ); + return options; + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetNonOptionArgumentsImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetNonOptionArgumentsImmutabilityTest.java new file mode 100644 index 0000000000..7a2f352a51 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetNonOptionArgumentsImmutabilityTest.java @@ -0,0 +1,56 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.Collections; +import java.util.List; + +import org.infinitest.toolkit.UnmodifiableListTestSupport; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class OptionSetNonOptionArgumentsImmutabilityTest extends UnmodifiableListTestSupport<String> { + @SuppressWarnings( "unchecked" ) + @Override + protected List<String> newList() { + OptionSet options = new OptionSet( Collections.<String, AbstractOptionSpec<?>> emptyMap() ); + NonOptionArgumentSpec<String> nonOptions = new NonOptionArgumentSpec<>( null ); + options.addWithArgument( nonOptions, "1" ); + options.addWithArgument( nonOptions, "2" ); + return (List<String>) options.nonOptionArguments(); + } + + @Override + protected String newItem() { + return "3"; + } + + @Override + protected String containedItem() { + return "2"; + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetSpecsImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetSpecsImmutabilityTest.java new file mode 100644 index 0000000000..d728828c12 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetSpecsImmutabilityTest.java @@ -0,0 +1,53 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.Collections; +import java.util.List; + +import org.infinitest.toolkit.UnmodifiableListTestSupport; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class OptionSetSpecsImmutabilityTest extends UnmodifiableListTestSupport<OptionSpec<?>> { + @Override + protected List<OptionSpec<?>> newList() { + OptionSet options = new OptionSet( Collections.<String, AbstractOptionSpec<?>> emptyMap() ); + options.add( new NoArgumentOptionSpec( "a" ) ); + return options.specs(); + } + + @Override + protected OptionSpec<?> newItem() { + return new NoArgumentOptionSpec( "b" ); + } + + @Override + protected OptionSpec<?> containedItem() { + return new NoArgumentOptionSpec( "a" ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetValuesOfOptionStringImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetValuesOfOptionStringImmutabilityTest.java new file mode 100644 index 0000000000..6f5189a196 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetValuesOfOptionStringImmutabilityTest.java @@ -0,0 +1,57 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.Collections; +import java.util.List; + +import org.infinitest.toolkit.UnmodifiableListTestSupport; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class OptionSetValuesOfOptionStringImmutabilityTest extends UnmodifiableListTestSupport<Object> { + @SuppressWarnings( "unchecked" ) + @Override + protected List<Object> newList() { + RequiredArgumentOptionSpec<String> optionB = new RequiredArgumentOptionSpec<>( "b" ); + OptionSet options = new OptionSet( Collections.<String, AbstractOptionSpec<?>> emptyMap() ); + options.addWithArgument( optionB, "foo" ); + options.addWithArgument( optionB, "bar" ); + + return (List<Object>) options.valuesOf( "b" ); + } + + @Override + protected String newItem() { + return "baz"; + } + + @Override + protected String containedItem() { + return "bar"; + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetValuesOfSpecImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetValuesOfSpecImmutabilityTest.java new file mode 100644 index 0000000000..146652a861 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSetValuesOfSpecImmutabilityTest.java @@ -0,0 +1,55 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.Collections; +import java.util.List; + +import org.infinitest.toolkit.UnmodifiableListTestSupport; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class OptionSetValuesOfSpecImmutabilityTest extends UnmodifiableListTestSupport<String> { + @Override + protected List<String> newList() { + RequiredArgumentOptionSpec<String> optionA = new RequiredArgumentOptionSpec<>( "a" ); + OptionSet options = new OptionSet( Collections.<String, AbstractOptionSpec<?>> emptyMap() ); + options.addWithArgument( optionA, "anArgument" ); + options.addWithArgument( optionA, "anotherArgument" ); + return options.valuesOf( optionA ); + } + + @Override + protected String newItem() { + return "yetAnotherArgument"; + } + + @Override + protected String containedItem() { + return "anArgument"; + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSpecBuilderOptionsImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSpecBuilderOptionsImmutabilityTest.java new file mode 100644 index 0000000000..231e690cc3 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSpecBuilderOptionsImmutabilityTest.java @@ -0,0 +1,38 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Arrays.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class OptionSpecBuilderOptionsImmutabilityTest extends AbstractOptionSpecOptionsImmutabilityTestCase { + @Override + protected AbstractOptionSpec<?> newOptionSpec( String option ) { + return new OptionSpecBuilder( new OptionParser(), asList( option ), "" ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSpecBuilderValuesImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSpecBuilderValuesImmutabilityTest.java new file mode 100644 index 0000000000..3adc17dadc --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSpecBuilderValuesImmutabilityTest.java @@ -0,0 +1,58 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Arrays.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class OptionSpecBuilderValuesImmutabilityTest extends AbstractOptionSpecValuesImmutabilityTestCase<Void> { + @Override + protected AbstractOptionSpec<Void> newOptionSpec() { + return new OptionSpecBuilder( new OptionParser(), asList( "a" ), "" ); + } + + @Override + protected String firstArg() { + return "Q"; + } + + @Override + protected String secondArg() { + return "W"; + } + + @Override + protected Void newItem() { + return null; + } + + @Override + protected Void containedItem() { + return null; + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSpecTokenizerTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSpecTokenizerTest.java new file mode 100644 index 0000000000..6e403078f7 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSpecTokenizerTest.java @@ -0,0 +1,205 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.NoSuchElementException; + +import static java.util.Collections.*; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static org.infinitest.toolkit.CollectionMatchers.*; +import static org.junit.Assert.*; +import static org.junit.rules.ExpectedException.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class OptionSpecTokenizerTest { + @Rule public final ExpectedException thrown = none(); + + @Test + public void tokenizeEmpty() { + assertNoMoreTokens( new OptionSpecTokenizer( "" ) ); + } + + @Test + public void tokenizeOptionsWithoutArguments() { + OptionSpecTokenizer lexer = new OptionSpecTokenizer( "ab" ); + assertNextTokenTakesNoArgument( lexer, 'a', false ); + assertNextTokenTakesNoArgument( lexer, 'b', false ); + assertNoMoreTokens( lexer ); + } + + @Test + public void tokenizeOptionsWithRequiredArguments() { + OptionSpecTokenizer lexer = new OptionSpecTokenizer( "c:d:" ); + assertNextTokenRequiresAnArgument( lexer, 'c', false ); + assertNextTokenRequiresAnArgument( lexer, 'd', false ); + assertNoMoreTokens( lexer ); + } + + @Test + public void tokenizeOptionsWithOptionalArguments() { + OptionSpecTokenizer lexer = new OptionSpecTokenizer( "e::f::" ); + assertNextTokenTakesAnOptionalArgument( lexer, 'e', false ); + assertNextTokenTakesAnOptionalArgument( lexer, 'f', false ); + assertNoMoreTokens( lexer ); + } + + @Test + public void tokenizeOptionsWithMixtureOfSpecTypes() { + OptionSpecTokenizer lexer = new OptionSpecTokenizer( "gh:i::j" ); + assertNextTokenTakesNoArgument( lexer, 'g', false ); + assertNextTokenRequiresAnArgument( lexer, 'h', false ); + assertNextTokenTakesAnOptionalArgument( lexer, 'i', false ); + assertNextTokenTakesNoArgument( lexer, 'j', false ); + assertNoMoreTokens( lexer ); + } + + @Test + public void wByItself() { + OptionSpecTokenizer lexer = new OptionSpecTokenizer( "W" ); + assertNextTokenTakesNoArgument( lexer, 'W', false ); + assertNoMoreTokens( lexer ); + } + + @Test + public void wRequiredArg() { + OptionSpecTokenizer lexer = new OptionSpecTokenizer( "W:" ); + assertNextTokenRequiresAnArgument( lexer, 'W', false ); + assertNoMoreTokens( lexer ); + } + + @Test + public void wOptionalArg() { + OptionSpecTokenizer lexer = new OptionSpecTokenizer( "W::" ); + assertNextTokenTakesAnOptionalArgument( lexer, 'W', false ); + assertNoMoreTokens( lexer ); + } + + @Test + public void alternativeLongOptionsMarker() { + OptionSpecTokenizer lexer = new OptionSpecTokenizer( "W;" ); + assertNextTokenRequiresAnArgument( lexer, 'W', false ); + assertNoMoreTokens( lexer ); + } + + @Test + public void tokenizeOptionsWithoutArgumentsAndHelpMarker() { + OptionSpecTokenizer lexer = new OptionSpecTokenizer( "ab*" ); + assertNextTokenTakesNoArgument( lexer, 'a', false ); + assertNextTokenTakesNoArgument( lexer, 'b', true ); + assertNoMoreTokens( lexer ); + } + + @Test + public void tokenizeOptionsWithRequiredArgumentsAndHelpMarker() { + OptionSpecTokenizer lexer = new OptionSpecTokenizer( "c*:d:" ); + assertNextTokenRequiresAnArgument( lexer, 'c', true ); + assertNextTokenRequiresAnArgument( lexer, 'd', false ); + assertNoMoreTokens( lexer ); + } + + @Test + public void tokenizeOptionsWithOptionalArgumentsAndHelpMarker() { + OptionSpecTokenizer lexer = new OptionSpecTokenizer( "e*::f*::" ); + assertNextTokenTakesAnOptionalArgument( lexer, 'e', true ); + assertNextTokenTakesAnOptionalArgument( lexer, 'f', true ); + assertNoMoreTokens( lexer ); + } + + @Test + public void tokenizeOptionsWithMixtureOfSpecTypesAndHelpMarker() { + OptionSpecTokenizer lexer = new OptionSpecTokenizer( "g*h:i*::j" ); + assertNextTokenTakesNoArgument( lexer, 'g', true ); + assertNextTokenRequiresAnArgument( lexer, 'h', false ); + assertNextTokenTakesAnOptionalArgument( lexer, 'i', true ); + assertNextTokenTakesNoArgument( lexer, 'j', false ); + assertNoMoreTokens( lexer ); + } + + @Test + public void wByItselfWithHelpMarker() { + OptionSpecTokenizer lexer = new OptionSpecTokenizer( "W*" ); + assertNextTokenTakesNoArgument( lexer, 'W', true ); + assertNoMoreTokens( lexer ); + } + + @Test + public void wRequiredArgWithHelpMarker() { + OptionSpecTokenizer lexer = new OptionSpecTokenizer( "W*:" ); + assertNextTokenRequiresAnArgument( lexer, 'W', true ); + assertNoMoreTokens( lexer ); + } + + @Test + public void wOptionalArgWithHelpMarker() { + OptionSpecTokenizer lexer = new OptionSpecTokenizer( "W*::" ); + assertNextTokenTakesAnOptionalArgument( lexer, 'W', true ); + assertNoMoreTokens( lexer ); + } + + @Test + public void alternativeLongOptionsMarkerWithHelpMarker() { + OptionSpecTokenizer lexer = new OptionSpecTokenizer( "W*;" ); + assertNextTokenTakesNoArgument( lexer, 'W', true ); + } + + private void assertNoMoreTokens( OptionSpecTokenizer lexer ) { + assertFalse( lexer.hasMore() ); + + thrown.expect( NoSuchElementException.class ); + lexer.next(); + } + + private static void assertNextTokenTakesNoArgument( OptionSpecTokenizer lexer, char option, boolean forHelp ) { + assertNextToken( lexer, option, false, false, forHelp ); + } + + private static void assertNextTokenRequiresAnArgument( OptionSpecTokenizer lexer, char option, boolean forHelp ) { + assertNextToken( lexer, option, true, true, forHelp ); + } + + private static void assertNextTokenTakesAnOptionalArgument( OptionSpecTokenizer lexer, char option, + boolean forHelp ) { + + assertNextToken( lexer, option, true, false, forHelp ); + } + + private static void assertNextToken( OptionSpecTokenizer lexer, char option, boolean acceptsArguments, + boolean requiresArgument, boolean forHelp ) { + + assertTrue( "no more tokens?", lexer.hasMore() ); + AbstractOptionSpec<?> spec = lexer.next(); + assertThat( "option?", spec.options(), hasSameContentsAs( singleton( String.valueOf( option ) ) ) ); + assertEquals( "accepts args?", acceptsArguments, spec.acceptsArguments() ); + assertEquals( "requires arg?", requiresArgument, spec.requiresArgument() ); + assertEquals( "for help?", forHelp, spec.isForHelp() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSpecsReportTheirOptionsSortedSpeciallyTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSpecsReportTheirOptionsSortedSpeciallyTest.java new file mode 100644 index 0000000000..ff531dd198 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSpecsReportTheirOptionsSortedSpeciallyTest.java @@ -0,0 +1,49 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.ArrayList; +import java.util.List; + +import static java.util.Arrays.*; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class OptionSpecsReportTheirOptionsSortedSpeciallyTest { + @Test + public void shortOptionsComeFirstFollowedByLongOptionsLexicographically() { + AbstractOptionSpec<Void> spec = new NoArgumentOptionSpec( asList( "after-date", "n", "N", "past" ), "" ); + + List<String> actualOptions = new ArrayList<>( spec.options() ); + + assertEquals( asList( "N", "n", "after-date", "past" ), actualOptions ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymCommonPrefixesTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymCommonPrefixesTest.java new file mode 100644 index 0000000000..986761d7ff --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymCommonPrefixesTest.java @@ -0,0 +1,88 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Arrays.*; + +import org.junit.Before; +import org.junit.Test; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class OptionSynonymCommonPrefixesTest extends AbstractOptionParserFixture { + @Before + public final void initializeParser() { + parser.acceptsAll( asList( "v", "verbose" ) ); + } + + @Test + public void parsingFirstPrefix() { + assertDetections( "-v" ); + } + + @Test + public void parsingSecondPrefix() { + assertDetections( "-ve" ); + } + + @Test + public void parsingThirdPrefix() { + assertDetections( "-ver" ); + } + + @Test + public void parsingFourthPrefix() { + assertDetections( "-verb" ); + } + + @Test + public void parsingFifthPrefix() { + assertDetections( "-verbo" ); + } + + @Test + public void parsingSixthPrefix() { + assertDetections( "-verbos" ); + } + + @Test + public void parsingSeventhPrefix() { + assertDetections( "-verbose" ); + } + + private void assertDetections( String option ) { + OptionSet options = parser.parse( option ); + + assertOptionDetected( options, "v" ); + assertOptionNotDetected( options, "ve" ); + assertOptionNotDetected( options, "ver" ); + assertOptionNotDetected( options, "verb" ); + assertOptionNotDetected( options, "verbo" ); + assertOptionNotDetected( options, "verbos" ); + assertOptionDetected( options, "verbose" ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymNoArgumentTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymNoArgumentTest.java new file mode 100644 index 0000000000..2b66176194 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymNoArgumentTest.java @@ -0,0 +1,71 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Arrays.*; +import static java.util.Collections.*; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class OptionSynonymNoArgumentTest extends AbstractOptionParserFixture { + @Before + public final void initializeParser() { + parser.acceptsAll( asList( "N", "after-date", "newer" ) ); + } + + @Test + public void hasAllSynonymsWhenFirstSynonymParsed() { + assertDetections( "-N" ); + } + + @Test + public void hasAllSynonymsWhenSecondSynonymParsed() { + assertDetections( "--after-d" ); + } + + @Test + public void hasAllSynonymsWhenThirdSynonymParsed() { + assertDetections( "--n" ); + } + + private void assertDetections( String option ) { + OptionSet options = parser.parse( option ); + + assertOptionDetected( options, "N" ); + assertOptionDetected( options, "after-date" ); + assertOptionDetected( options, "newer" ); + assertEquals( emptyList(), options.valuesOf( "N" ) ); + assertEquals( emptyList(), options.valuesOf( "after-date" ) ); + assertEquals( emptyList(), options.valuesOf( "newer" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymOptionalArgumentTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymOptionalArgumentTest.java new file mode 100644 index 0000000000..5ff03e5cba --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymOptionalArgumentTest.java @@ -0,0 +1,80 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.io.File; +import java.util.List; + +import static java.util.Arrays.*; +import static java.util.Collections.*; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class OptionSynonymOptionalArgumentTest extends AbstractOptionParserFixture { + private String optionArgument; + + @Before + public final void initializeParser() { + parser.acceptsAll( asList( "d", "output-dir", "folder" ), "file" ).withRequiredArg().ofType( File.class ); + optionArgument = "tmp"; + } + + @Test + public void hasAllSynonymsWhenFirstSynonymParsed() { + assertDetections( new String[] { "-d", optionArgument }, singletonList( new File( optionArgument ) ) ); + } + + @Test + public void hasAllSynonymsWhenSecondSynonymParsed() { + assertDetections( new String[] { "--ou", optionArgument }, singletonList( new File( optionArgument ) ) ); + } + + @Test + public void hasAllSynonymsWhenThirdSynonymParsed() { + assertDetections( new String[] { "--fold", optionArgument }, singletonList( new File( optionArgument ) ) ); + } + + @Test + public void reportsSameListOfArgumentsForEverySynonymOption() { + assertDetections( + new String[] { "-d", "opt", "--output-dir", "tmp", "--folder", "usr" }, + asList( new File( "opt" ), new File( "tmp" ), new File( "usr" ) ) ); + } + + private void assertDetections( String[] args, List<?> optionArguments ) { + OptionSet options = parser.parse( args ); + assertEquals( optionArguments, options.valuesOf( "d" ) ); + assertEquals( optionArguments, options.valuesOf( "output-dir" ) ); + assertEquals( optionArguments, options.valuesOf( "folder" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymOverwritingTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymOverwritingTest.java new file mode 100644 index 0000000000..3294d341fa --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymOverwritingTest.java @@ -0,0 +1,51 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Arrays.*; + +import org.junit.Before; +import org.junit.Test; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class OptionSynonymOverwritingTest extends AbstractOptionParserFixture { + @Before + public final void initializeParser() { + parser.acceptsAll( asList( "h", "help" ) ); + parser.acceptsAll( asList( "h", "oops" ) ); + } + + @Test + public void treatsHAsThoughItWereLastDefinedSynonymOfH() { + OptionSet options = parser.parse( "-h" ); + + assertOptionDetected( options, "h" ); + assertOptionDetected( options, "oops" ); + assertOptionNotDetected( options, "help" ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymRequiredArgumentTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymRequiredArgumentTest.java new file mode 100644 index 0000000000..10d788907d --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionSynonymRequiredArgumentTest.java @@ -0,0 +1,82 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.List; + +import static java.util.Arrays.*; +import static java.util.Collections.*; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class OptionSynonymRequiredArgumentTest extends AbstractOptionParserFixture { + private String optionArgument; + + @Before + public final void initializeParser() { + parser.acceptsAll( asList( "N", "after-date", "newer" ), "date" ).withRequiredArg().ofType( Integer.class ); + optionArgument = "2000"; + } + + @Test + public void hasAllSynonymsWhenFirstSynonymParsed() { + assertDetections( new String[] { "-N", optionArgument }, singletonList( Integer.valueOf( optionArgument ) ) ); + } + + @Test + public void hasAllSynonymsWhenSecondSynonymParsed() { + assertDetections( + new String[] { "--after-date", optionArgument }, + singletonList( Integer.valueOf( optionArgument ) ) ); + } + + @Test + public void hasAllSynonymsWhenThirdSynonymParsed() { + assertDetections( + new String[] { "--newer", optionArgument }, + singletonList( Integer.valueOf( optionArgument ) ) ); + } + + @Test + public void reportsSameListOfArgumentsForEverySynonymOption() { + assertDetections( new String[] { "-N", "1", "-aft", "2", "--ne", "3" }, asList( 1, 2, 3 ) ); + } + + private void assertDetections( String[] args, List<?> optionArguments ) { + OptionSet options = parser.parse( args ); + + assertEquals( optionArguments, options.valuesOf( "N" ) ); + assertEquals( optionArguments, options.valuesOf( "after-date" ) ); + assertEquals( optionArguments, options.valuesOf( "newer" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionalArgumentOptionSpecOptionsImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionalArgumentOptionSpecOptionsImmutabilityTest.java new file mode 100644 index 0000000000..86765a55ab --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionalArgumentOptionSpecOptionsImmutabilityTest.java @@ -0,0 +1,36 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class OptionalArgumentOptionSpecOptionsImmutabilityTest extends AbstractOptionSpecOptionsImmutabilityTestCase { + @Override + protected AbstractOptionSpec<?> newOptionSpec( String option ) { + return new OptionalArgumentOptionSpec<Integer>( option ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionalArgumentOptionSpecTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionalArgumentOptionSpecTest.java new file mode 100644 index 0000000000..6f5c275ced --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionalArgumentOptionSpecTest.java @@ -0,0 +1,53 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Arrays.*; + +import org.junit.Test; + +import static org.infinitest.toolkit.CollectionMatchers.*; +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class OptionalArgumentOptionSpecTest extends AbstractOptionSpecFixture { + @Override + protected OptionalArgumentOptionSpec<?> createEqualOptionSpecInstance() { + return new OptionalArgumentOptionSpec<Void>( "d" ); + } + + @Override + protected OptionalArgumentOptionSpec<?> createNotEqualOptionSpecInstance() { + return new OptionalArgumentOptionSpec<Void>( "c" ); + } + + @Test + public void optionsContents() { + assertThat( createNotEqualOptionSpecInstance().options(), hasSameContentsAs( asList( "c" ) ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/OptionalArgumentOptionSpecValuesImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionalArgumentOptionSpecValuesImmutabilityTest.java new file mode 100644 index 0000000000..841b9460c7 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/OptionalArgumentOptionSpecValuesImmutabilityTest.java @@ -0,0 +1,58 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class OptionalArgumentOptionSpecValuesImmutabilityTest + extends AbstractOptionSpecValuesImmutabilityTestCase<Integer> { + + @Override + protected AbstractOptionSpec<Integer> newOptionSpec() { + return new OptionalArgumentOptionSpec<Integer>( "life" ).ofType( Integer.class ); + } + + @Override + protected String firstArg() { + return "1"; + } + + @Override + protected String secondArg() { + return "2"; + } + + @Override + protected Integer newItem() { + return 3; + } + + @Override + protected Integer containedItem() { + return 2; + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ParserRulesUtilityClassTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ParserRulesUtilityClassTest.java new file mode 100644 index 0000000000..82317befba --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ParserRulesUtilityClassTest.java @@ -0,0 +1,35 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class ParserRulesUtilityClassTest extends UtilityClassesUninstantiabilityHarness { + public ParserRulesUtilityClassTest() { + super( ParserRules.class ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ParsingSeparatedConvertedOptionValuesTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ParsingSeparatedConvertedOptionValuesTest.java new file mode 100644 index 0000000000..4e18003782 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ParsingSeparatedConvertedOptionValuesTest.java @@ -0,0 +1,82 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.io.File; + +import static java.util.Arrays.*; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class ParsingSeparatedConvertedOptionValuesTest extends AbstractOptionParserFixture { + @Test + public void parsesSeparatedValuesAsSeparateArgument() { + assertCorrectParse( "classpath", ':', "--classpath", "/usr:/opt:/var" ); + } + + @Test + public void parsesSeparatedValuesWhenArgumentAbuttedWithEquals() { + assertCorrectParse( "classpath", ':', "--classpath=/usr:/opt:/var" ); + } + + @Test + public void parsesEqualsSeparatedValuesWhenArgumentAbuttedWithEquals() { + assertCorrectParse( "classpath", '=', "--classpath=/usr=/opt=/var" ); + } + + @Test + public void parsesSeparatedValuesAbutting() { + assertCorrectParse( "c", ':', "-c/usr:/opt:/var" ); + } + + private void assertCorrectParse( String option, char separator, String... args ) { + parser.accepts( option ).withRequiredArg().withValuesSeparatedBy( separator ) + .withValuesConvertedBy( new ValueConverter<File>() { + public File convert( String value ) { + return new File( value ); + } + + public Class<File> valueType() { + return File.class; + } + + public String valuePattern() { + return null; + } + } ); + + OptionSet options = parser.parse( args ); + + assertEquals( + asList( new File( "/usr" ), new File( "/opt" ), new File( "/var" ) ), + options.valuesOf( option ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ParsingSeparatedStringOptionValuesTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ParsingSeparatedStringOptionValuesTest.java new file mode 100644 index 0000000000..6cfe17f862 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ParsingSeparatedStringOptionValuesTest.java @@ -0,0 +1,75 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Arrays.*; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class ParsingSeparatedStringOptionValuesTest extends AbstractOptionParserFixture { + @Test + public void parsesSeparatedValuesAsSeparateArgument() { + assertCorrectParse( "classpath", ":::", "--classpath", "/usr:::/opt:::/var" ); + } + + @Test + public void parsesSeparatedValuesWhenArgumentAbuttedWithEquals() { + assertCorrectParse( "classpath", ":", "--classpath=/usr:/opt:/var" ); + } + + @Test + public void parsesEqualsSeparatedValuesWhenArgumentAbuttedWithEquals() { + assertCorrectParse( "classpath", ":=", "--classpath=/usr:=/opt:=/var" ); + } + + @Test + public void parsesSeparatedValuesAbutting() { + assertCorrectParse( "c", ";", "-c/usr;/opt;/var" ); + } + + @Test + public void parsesHyphenSeparatedValuesAbutting() { + assertCorrectParse( "c", "--", "-c/usr--/opt--/var" ); + } + + @Test + public void handlesConsecutiveDelimiters() { + assertCorrectParse( "c", ",", "-c,/usr,,,/opt,,,/var,,,,," ); + } + + private void assertCorrectParse( String option, String separator, String... args ) { + parser.accepts( option ).withRequiredArg().withValuesSeparatedBy( separator ); + + OptionSet options = parser.parse( args ); + + assertEquals( asList( "/usr", "/opt", "/var" ), options.valuesOf( option ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ParsingSeparatedTypedOptionValuesTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ParsingSeparatedTypedOptionValuesTest.java new file mode 100644 index 0000000000..0cfc1e93fb --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ParsingSeparatedTypedOptionValuesTest.java @@ -0,0 +1,69 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.io.File; + +import static java.util.Arrays.*; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class ParsingSeparatedTypedOptionValuesTest extends AbstractOptionParserFixture { + @Test + public void parsesSeparatedValuesAsSeparateArgument() { + assertCorrectParse( "classpath", ':', "--classpath", "/usr:/opt:/var" ); + } + + @Test + public void parsesSeparatedValuesWhenArgumentAbuttedWithEquals() { + assertCorrectParse( "classpath", ':', "--classpath=/usr:/opt:/var" ); + } + + @Test + public void parsesEqualsSeparatedValuesWhenArgumentAbuttedWithEquals() { + assertCorrectParse( "classpath", '=', "--classpath=/usr=/opt=/var" ); + } + + @Test + public void parsesSeparatedValuesAbutting() { + assertCorrectParse( "c", ':', "-c/usr:/opt:/var" ); + } + + private void assertCorrectParse( String option, char separator, String... args ) { + parser.accepts( option ).withRequiredArg().ofType( File.class ).withValuesSeparatedBy( separator ); + + OptionSet options = parser.parse( args ); + + assertEquals( + asList( new File( "/usr" ), new File( "/opt" ), new File( "/var" ) ), + options.valuesOf( option ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/PlainOldOptionParserTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/PlainOldOptionParserTest.java new file mode 100644 index 0000000000..3fe8f509f8 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/PlainOldOptionParserTest.java @@ -0,0 +1,46 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Arrays.*; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class PlainOldOptionParserTest extends AbstractOptionParserFixture { + @Test + public void nonOptionsOnly() { + String[] arguments = { "foo", "bar" }; + + OptionSet options = parser.parse( arguments ); + + assertEquals( asList( arguments ), options.nonOptionArguments() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/PopulatedOptionSetTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/PopulatedOptionSetTest.java new file mode 100644 index 0000000000..5ac50368d2 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/PopulatedOptionSetTest.java @@ -0,0 +1,72 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package joptsimple; + +import java.util.Collections; + +import static java.util.Collections.*; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class PopulatedOptionSetTest { + private OptionSet populated; + + @Before + public void setUp() { + populated = new OptionSet( Collections.<String, AbstractOptionSpec<?>> emptyMap() ); + populated.add( new NoArgumentOptionSpec( "a" ) ); + populated.addWithArgument( new RequiredArgumentOptionSpec<String>( "b" ), "arg-of-b" ); + } + + @Test + public void hasArgument() { + assertFalse( populated.hasArgument( "a" ) ); + assertTrue( populated.hasArgument( "b" ) ); + } + + @Test + public void valueOf() { + assertNull( populated.valueOf( "a" ) ); + assertEquals( "arg-of-b", populated.valueOf( "b" ) ); + } + + @Test + public void valuesOf() { + assertEquals( emptyList(), populated.valuesOf( "a" ) ); + assertEquals( singletonList( "arg-of-b" ), populated.valuesOf( "b" ) ); + } + + @Test + public void hasOptions() { + assertTrue( populated.hasOptions() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/PosixlyCorrectOptionParserTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/PosixlyCorrectOptionParserTest.java new file mode 100644 index 0000000000..027c0a29c7 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/PosixlyCorrectOptionParserTest.java @@ -0,0 +1,74 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.Collection; + +import static java.util.Arrays.*; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +@RunWith( Parameterized.class ) +public class PosixlyCorrectOptionParserTest { + private final OptionParser parser; + + public PosixlyCorrectOptionParserTest( OptionParser parser ) { + this.parser = parser; + } + + @Parameterized.Parameters + public static Collection<?> parsers() { + return asList( new Object[] { + new OptionParser() { { + posixlyCorrect( true ); + accepts( "i" ).withRequiredArg(); + accepts( "j" ).withOptionalArg(); + accepts( "k" ); + } } }, + new Object[] { new OptionParser( "+i:j::k" ) } ); + } + + @Test + public void parseWithPosixlyCorrect() { + OptionSet options = + parser.parse( "-ibar", "-i", "junk", "xyz", "-jixnay", "foo", "-k", "blah", "--", "yermom" ); + + assertTrue( "i?", options.has( "i" ) ); + assertFalse( "j?", options.has( "j" ) ); + assertFalse( "k?", options.has( "k" ) ); + assertEquals( "args of i?", asList( "bar", "junk" ), options.valuesOf( "i" ) ); + assertEquals( "non-option args?", + asList( "xyz", "-jixnay", "foo", "-k", "blah", "--", "yermom" ), + options.nonOptionArguments() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/PunctuationInLongOptionTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/PunctuationInLongOptionTest.java new file mode 100644 index 0000000000..94e4e23a76 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/PunctuationInLongOptionTest.java @@ -0,0 +1,73 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class PunctuationInLongOptionTest extends AbstractOptionParserFixture { + @Test + public void allowsHyphensInTheMiddleOfOptionNames() { + assertOptionAllowed( "hyphenated-option" ); + } + + @Test + public void allowsHyphensPrettyMuchAnywhereButTheFront() { + assertOptionAllowed( "a-cra-zy-but-le--gal---o-p-t-i-o--n-----" ); + } + + @Test( expected = IllegalOptionSpecificationException.class ) + public void disallowsHyphensAtFrontOfOptionName() { + parser.accepts( "-weird-option" ); + } + + @Test + public void allowsDotInOptionNames() { + assertOptionAllowed( "..what.is.the.d..e...a....l..." ); + } + + @Test + public void allowsQuestionMarkInOptionNames() { + assertOptionAllowed( "??who?k??n???e????w?" ); + } + + @Test + public void allowsUnderscoreInOptionNames() { + assertOptionAllowed( "super_long_option_name" ); + } + + private void assertOptionAllowed( String option ) { + parser.accepts( option ); + + OptionSet options = parser.parse( "--" + option ); + + assertTrue( options.has( option ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/PunctuationInShortOptionTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/PunctuationInShortOptionTest.java new file mode 100644 index 0000000000..20565b9b9b --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/PunctuationInShortOptionTest.java @@ -0,0 +1,61 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class PunctuationInShortOptionTest { + @Test( expected = IllegalOptionSpecificationException.class ) + public void disallowsHyphenAsShortOption() { + new OptionParser( "-" ); + } + + @Test + public void allowsQuestionMarkAsShortOption() { + assertOptionAllowed( "?" ); + } + + @Test + public void allowsDotAsShortOption() { + assertOptionAllowed( "." ); + } + + @Test + public void allowsUnderscoreAsShortOption() { + assertOptionAllowed( "_" ); + } + + private void assertOptionAllowed( String option ) { + OptionSet options = new OptionParser( option ).parse( '-' + option ); + + assertTrue( options.has( option ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredArgumentOptionSpecEqualsHashCodeTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredArgumentOptionSpecEqualsHashCodeTest.java new file mode 100644 index 0000000000..9235d5cc12 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredArgumentOptionSpecEqualsHashCodeTest.java @@ -0,0 +1,41 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class RequiredArgumentOptionSpecEqualsHashCodeTest extends AbstractOptionSpecFixture { + @Override + protected RequiredArgumentOptionSpec<?> createEqualOptionSpecInstance() { + return new RequiredArgumentOptionSpec<Void>( "a" ); + } + + @Override + protected RequiredArgumentOptionSpec<?> createNotEqualOptionSpecInstance() { + return new RequiredArgumentOptionSpec<Void>( "b" ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredArgumentOptionSpecOptionsImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredArgumentOptionSpecOptionsImmutabilityTest.java new file mode 100644 index 0000000000..e834d1b745 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredArgumentOptionSpecOptionsImmutabilityTest.java @@ -0,0 +1,36 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class RequiredArgumentOptionSpecOptionsImmutabilityTest extends AbstractOptionSpecOptionsImmutabilityTestCase { + @Override + protected AbstractOptionSpec<?> newOptionSpec( String option ) { + return new RequiredArgumentOptionSpec<String>( option ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredArgumentOptionSpecValuesImmutabilityTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredArgumentOptionSpecValuesImmutabilityTest.java new file mode 100644 index 0000000000..f75a068b75 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredArgumentOptionSpecValuesImmutabilityTest.java @@ -0,0 +1,58 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class RequiredArgumentOptionSpecValuesImmutabilityTest + extends AbstractOptionSpecValuesImmutabilityTestCase<String> { + + @Override + protected AbstractOptionSpec<String> newOptionSpec() { + return new RequiredArgumentOptionSpec<>( "file" ); + } + + @Override + protected String firstArg() { + return "arg1"; + } + + @Override + protected String secondArg() { + return "arg2"; + } + + @Override + protected String newItem() { + return "arg3"; + } + + @Override + protected String containedItem() { + return "arg1"; + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredIfAnyTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredIfAnyTest.java new file mode 100644 index 0000000000..75c39d8121 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredIfAnyTest.java @@ -0,0 +1,86 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Collections.*; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class RequiredIfAnyTest extends AbstractOptionParserFixture { + @Before + public void configureParser() { + parser.accepts( "a" ); + parser.accepts( "b" ); + OptionSpec<Void> c = parser.accepts( "c" ); + OptionSpec<Void> d = parser.accepts( "d" ); + parser.accepts( "e" ); + parser.accepts( "n" ).requiredIf( "a", "b" ).requiredIf( c, d ); + } + + @Test + public void rejectsCommandLineMissingConditionallyRequiredOption() { + thrown.expect( MissingRequiredOptionsException.class ); + + parser.parse( "-a" ); + } + + @Test + public void rejectsCommandLineMissingOtherConditionallyRequiredOption() { + thrown.expect( MissingRequiredOptionsException.class ); + + parser.parse( "-b" ); + } + + @Test + public void rejectsCommandLineWithNotAllConditionallyRequiredOptionsPresent() { + thrown.expect( MissingRequiredOptionsException.class ); + + parser.parse( "-a", "-b", "-c", "-d" ); + } + + @Test + public void acceptsCommandLineWithConditionallyRequiredOptionsPresent() { + OptionSet options = parser.parse( "-b", "-n" ); + + assertOptionDetected( options, "b" ); + assertOptionDetected( options, "n" ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void acceptsOptionWithPrerequisiteAsNormalIfPrerequisiteNotInPlay() { + OptionSet options = parser.parse( "-n" ); + + assertOptionDetected( options, "n" ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredIfTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredIfTest.java new file mode 100644 index 0000000000..d5cbb17c28 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredIfTest.java @@ -0,0 +1,112 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Arrays.*; +import static java.util.Collections.*; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class RequiredIfTest extends AbstractOptionParserFixture { + @Before + public void configureParser() { + OptionSpec<Void> ftp = parser.acceptsAll( asList( "ftp", "file-transfer" ) ); + parser.acceptsAll( asList( "username", "userid" ) ).requiredIf( "file-transfer" ).withRequiredArg(); + parser.acceptsAll( asList( "password", "pwd" ) ).requiredIf( ftp ).withRequiredArg(); + parser.accepts( "?" ).forHelp(); + } + + @Test + public void rejectsCommandLineMissingConditionallyRequiredOption() { + thrown.expect( MissingRequiredOptionsException.class ); + + parser.parse( "--ftp" ); + } + + @Test + public void rejectsCommandLineMissingConditionallyRequiredOptionSynonym() { + thrown.expect( MissingRequiredOptionsException.class ); + + parser.parse( "--file-transfer" ); + } + + @Test + public void rejectsCommandLineWithNotAllConditionallyRequiredOptionsPresent() { + thrown.expect( MissingRequiredOptionsException.class ); + + parser.parse( "--ftp", "--username", "joe" ); + } + + @Test + public void acceptsCommandLineWithConditionallyRequiredOptionsPresent() { + OptionSet options = parser.parse( "--ftp", "--userid", "joe", "--password=secret" ); + + assertOptionDetected( options, "ftp" ); + assertOptionDetected( options, "username" ); + assertOptionDetected( options, "password" ); + assertEquals( singletonList( "joe" ), options.valuesOf( "username" ) ); + assertEquals( singletonList( "secret" ), options.valuesOf( "password" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void acceptsOptionWithPrerequisiteAsNormalIfPrerequisiteNotInPlay() { + OptionSet options = parser.parse( "--pwd", "secret" ); + + assertOptionDetected( options, "pwd" ); + assertEquals( singletonList( "secret" ), options.valuesOf( "pwd" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void rejectsOptionNotAlreadyConfigured() { + thrown.expect( UnconfiguredOptionException.class ); + + parser.accepts( "foo" ).requiredIf( "bar" ); + } + + @Test + public void rejectsOptionSpecNotAlreadyConfigured() { + thrown.expect( UnconfiguredOptionException.class ); + + parser.accepts( "foo" ).requiredIf( "bar" ); + } + + @Test + public void presenceOfHelpOptionNegatesRequiredIfness() { + OptionSet options = parser.parse( "--ftp", "-?" ); + + assertOptionDetected( options, "ftp" ); + assertOptionDetected( options, "?" ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredUnlessAnyTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredUnlessAnyTest.java new file mode 100644 index 0000000000..d61dd78206 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredUnlessAnyTest.java @@ -0,0 +1,78 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import org.junit.Before; +import org.junit.Test; + +import static java.util.Collections.emptyList; +import static org.junit.Assert.assertEquals; + +public class RequiredUnlessAnyTest extends AbstractOptionParserFixture { + @Before + public void configureParser() { + parser.accepts( "a" ); + parser.accepts( "b" ); + OptionSpec<Void> c = parser.accepts( "c" ); + OptionSpec<Void> d = parser.accepts( "d" ); + parser.accepts( "e" ); + parser.accepts( "n" ).requiredUnless( "a", "b" ).requiredUnless( c, d ); + } + + @Test + public void commandLineMissingConditionallyRequiredOption() { + OptionSet options = parser.parse( "-a" ); + assertOptionDetected( options, "a" ); + assertOptionNotDetected( options, "n" ); + } + + @Test + public void commandLineWithNotAllConditionallyRequiredOptionsPresent() { + OptionSet options = parser.parse( "-a", "-b", "-c", "-d" ); + assertOptionDetected( options, "a" ); + assertOptionDetected( options, "b" ); + assertOptionDetected( options, "c" ); + assertOptionDetected( options, "d" ); + assertOptionNotDetected( options, "n" ); + } + + @Test + public void acceptsCommandLineWithConditionallyRequiredOptionsPresent() { + OptionSet options = parser.parse( "-n" ); + + assertOptionDetected( options, "n" ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void acceptsOptionWithPrerequisiteAsNormalIfPrerequisiteNotInPlay() { + OptionSet options = parser.parse( "-a", "-n" ); + + assertOptionDetected( options, "a" ); + assertOptionDetected( options, "n" ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredUnlessTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredUnlessTest.java new file mode 100644 index 0000000000..ed5b47b023 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/RequiredUnlessTest.java @@ -0,0 +1,110 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import org.junit.Before; +import org.junit.Test; + +import static java.util.Arrays.asList; +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; +import static org.junit.Assert.assertEquals; + +public class RequiredUnlessTest extends AbstractOptionParserFixture { + @Before + public void configureParser() { + OptionSpec<Void> anonymous = parser.accepts( "anonymous" ); + parser.acceptsAll( asList( "username", "userid" ) ).requiredUnless( "anonymous" ).withRequiredArg(); + parser.acceptsAll( asList( "password", "pwd" ) ).requiredUnless( anonymous ).withRequiredArg(); + parser.accepts( "?" ).forHelp(); + } + + @Test + public void rejectsCommandLineMissingConditionallyRequiredOption() { + thrown.expect( MissingRequiredOptionsException.class ); + + parser.parse( "" ); + } + + @Test + public void rejectsCommandLineWithNotAllConditionallyRequiredOptionsPresent() { + thrown.expect( MissingRequiredOptionsException.class ); + + parser.parse( "--username", "joe" ); + } + + @Test + public void acceptsCommandLineWithConditionallyRequiredOptionsPresent() { + OptionSet options = parser.parse( "--userid", "joe", "--password=secret" ); + + assertOptionNotDetected( options, "anonymous" ); + assertOptionDetected( options, "username" ); + assertOptionDetected( options, "password" ); + assertEquals( singletonList( "joe" ), options.valuesOf( "username" ) ); + assertEquals( singletonList( "secret" ), options.valuesOf( "password" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void acceptsOptionWithPrerequisite() { + OptionSet options = parser.parse( "--anonymous" ); + + assertOptionDetected( options, "anonymous" ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void acceptsOptionWithPrerequisiteAsNormal() { + OptionSet options = parser.parse( "--anonymous", "--pwd", "secret" ); + + assertOptionDetected( options, "anonymous" ); + assertOptionDetected( options, "pwd" ); + assertEquals( singletonList( "secret" ), options.valuesOf( "pwd" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void rejectsOptionNotAlreadyConfigured() { + thrown.expect( UnconfiguredOptionException.class ); + + parser.accepts( "foo" ).requiredIf( "bar" ); + } + + @Test + public void rejectsOptionSpecNotAlreadyConfigured() { + thrown.expect( UnconfiguredOptionException.class ); + + parser.accepts( "foo" ).requiredIf( "bar" ); + } + + @Test + public void presenceOfHelpOptionNegatesRequiredUnlessness() { + OptionSet options = parser.parse( "-?" ); + + assertOptionDetected( options, "?" ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ShortOptionsNoArgumentTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ShortOptionsNoArgumentTest.java new file mode 100644 index 0000000000..6c2af89cda --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ShortOptionsNoArgumentTest.java @@ -0,0 +1,108 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Arrays.*; +import static java.util.Collections.*; + +import org.junit.Before; +import org.junit.Test; + +import static joptsimple.ParserRules.*; +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class ShortOptionsNoArgumentTest extends AbstractOptionParserFixture { + @Before + public final void initializeParser() { + parser.accepts( "a" ); + parser.accepts( "b" ); + parser.accepts( "c" ); + } + + @Test + public void singleOption() { + OptionSet options = parser.parse( "-a" ); + + assertOptionDetected( options, "a" ); + assertNull( options.valueOf( "a" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void twoSingleOptions() { + OptionSet options = parser.parse( "-a", "-b" ); + + assertOptionDetected( options, "a" ); + assertOptionDetected( options, "b" ); + assertNull( options.valueOf( "a" ) ); + assertNull( options.valueOf( "b" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void singleOptionWithOneNonOptionArgument() { + OptionSet options = parser.parse( "-c", "foo" ); + + assertOptionDetected( options, "c" ); + assertNull( options.valueOf( "c" ) ); + assertEquals( singletonList( "foo" ), options.nonOptionArguments() ); + } + + @Test + public void clusteredOptions() { + OptionSet options = parser.parse( "-bac" ); + + assertOptionDetected( options, "a" ); + assertOptionDetected( options, "b" ); + assertOptionDetected( options, "c" ); + assertNull( options.valueOf( "a" ) ); + assertNull( options.valueOf( "b" ) ); + assertNull( options.valueOf( "c" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void optionsTerminator() { + OptionSet options = parser.parse( "-a", OPTION_TERMINATOR, "-a", "-b" ); + + assertOptionDetected( options, "a" ); + assertNull( options.valueOf( "a" ) ); + assertOptionNotDetected( options, "b" ); + assertEquals( asList( "-a", "-b" ), options.nonOptionArguments() ); + } + + @Test + public void appearingMultipleTimes() { + OptionSet options = parser.parse( "-b", "-b", "-b" ); + + assertOptionDetected( options, "b" ); + assertNull( options.valueOf( "b" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ShortOptionsOptionalArgumentTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ShortOptionsOptionalArgumentTest.java new file mode 100644 index 0000000000..3616d88c04 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ShortOptionsOptionalArgumentTest.java @@ -0,0 +1,103 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Arrays.*; +import static java.util.Collections.*; + +import org.junit.Before; +import org.junit.Test; + +import static joptsimple.ExceptionMatchers.*; +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class ShortOptionsOptionalArgumentTest extends AbstractOptionParserFixture { + @Before + public final void initializeParser() { + parser.accepts( "f" ).withOptionalArg(); + parser.accepts( "g" ).withOptionalArg(); + parser.accepts( "bar" ).withOptionalArg(); + } + + @Test + public void optionWithOptionalArgumentNotPresent() { + OptionSet options = parser.parse( "-f" ); + + assertOptionDetected( options, "f" ); + assertEquals( emptyList(), options.valuesOf( "f" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void optionWithOptionalArgumentPresent() { + OptionSet options = parser.parse( "-f", "bar" ); + + assertOptionDetected( options, "f" ); + assertEquals( singletonList( "bar" ), options.valuesOf( "f" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void optionWithOptionalArgumentThatLooksLikeAnInvalidOption() { + thrown.expect( UnrecognizedOptionException.class ); + thrown.expect( withOption( "biz" ) ); + + parser.parse( "-f", "--biz" ); + } + + @Test + public void optionWithOptionalArgumentThatLooksLikeAValidOption() { + OptionSet options = parser.parse( "-f", "--bar" ); + + assertOptionDetected( options, "f" ); + assertOptionDetected( options, "bar" ); + assertEquals( emptyList(), options.valuesOf( "f" ) ); + assertEquals( emptyList(), options.valuesOf( "bar" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void optionWithOptionalArgumentFollowedByLegalOption() { + OptionSet options = parser.parse( "-f", "-g" ); + + assertOptionDetected( options, "f" ); + assertOptionDetected( options, "g" ); + assertEquals( emptyList(), options.valuesOf( "f" ) ); + assertEquals( emptyList(), options.valuesOf( "g" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void multipleOfSameOptionSomeWithArgsAndSomeWithout() { + OptionSet options = parser.parse( "-f", "-f", "foo", "-f", "-f", "bar", "-f" ); + + assertEquals( asList( "foo", "bar" ), options.valuesOf( "f" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ShortOptionsRequiredArgumentTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ShortOptionsRequiredArgumentTest.java new file mode 100644 index 0000000000..dea86ca34e --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ShortOptionsRequiredArgumentTest.java @@ -0,0 +1,130 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Arrays.*; +import static java.util.Collections.*; + +import org.junit.Before; +import org.junit.Test; + +import static joptsimple.ExceptionMatchers.*; +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class ShortOptionsRequiredArgumentTest extends AbstractOptionParserFixture { + @Before + public final void initializeParser() { + parser.accepts( "d" ).withRequiredArg(); + parser.accepts( "e" ); + parser.accepts( "f" ); + parser.accepts( "infile" ).withOptionalArg(); + } + + @Test + public void argumentNotPresent() { + thrown.expect( OptionMissingRequiredArgumentException.class ); + thrown.expect( withOption( "d" ) ); + + parser.parse( "-d" ); + } + + @Test + public void withArgument() { + OptionSet options = parser.parse( "-d", "foo" ); + + assertOptionDetected( options, "d" ); + assertEquals( "foo", options.valueOf( "d" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void clusteredOptionsWithLastOneAcceptingAnArgumentButMissing() { + thrown.expect( OptionMissingRequiredArgumentException.class ); + + parser.parse( "-fed" ); + } + + @Test + public void clusteredOptionsWithLastOneAcceptingAnArgument() { + OptionSet options = parser.parse( "-fed", "foo" ); + + assertOptionDetected( options, "d" ); + assertOptionDetected( options, "f" ); + assertOptionDetected( options, "e" ); + assertEquals( "foo", options.valueOf( "d" ) ); + } + + @Test + public void clusteredOptionsWithOneAcceptingAnArgument() { + OptionSet options = parser.parse( "-fde" ); + + assertOptionDetected( options, "f" ); + assertOptionDetected( options, "d" ); + assertOptionNotDetected( options, "e" ); + + assertEquals( "e", options.valueOf( "d" ) ); + } + + @Test + public void argumentNotPresentFollowedByAnotherOption() { + OptionSet options = parser.parse( "-d", "--infile" ); + + assertOptionDetected( options, "d" ); + assertOptionNotDetected( options, "infile" ); + assertEquals( "--infile", options.valueOf( "d" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void appearingMultipleTimes() { + OptionSet options = parser.parse( "-d", "foo", "-d", "bar" ); + + assertOptionDetected( options, "d" ); + assertEquals( asList( "foo", "bar" ), options.valuesOf( "d" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void inSameToken() { + OptionSet options = parser.parse( "-dfoo" ); + + assertOptionDetected( options, "d" ); + assertEquals( singletonList( "foo" ), options.valuesOf( "d" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void whenEndOfOptionsMarkerIsInPlaceOfRequiredArgument() { + OptionSet options = parser.parse( "-d", "--", "foo", "bar" ); + + assertOptionDetected( options, "d" ); + assertEquals( singletonList( "--" ), options.valuesOf( "d" ) ); + assertEquals( asList( "foo", "bar" ), options.nonOptionArguments() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/SingleHyphenTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/SingleHyphenTest.java new file mode 100644 index 0000000000..7c88a7ddd2 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/SingleHyphenTest.java @@ -0,0 +1,68 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Collections.*; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class SingleHyphenTest extends AbstractOptionParserFixture { + @Before + public final void initializeParser() { + parser.accepts( "o" ).withOptionalArg(); + } + + @Test + public void singleHyphen() { + OptionSet options = parser.parse( "-" ); + + assertEquals( singletonList( "-" ), options.nonOptionArguments() ); + } + + @Test + public void asArgumentOfOption() { + OptionSet options = parser.parse( "-o", "-" ); + + assertOptionDetected( options, "o" ); + assertEquals( singletonList( "-" ), options.valuesOf( "o" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void asArgumentOfOptionInSameToken() { + OptionSet options = parser.parse( "-o-" ); + + assertOptionDetected( options, "o" ); + assertEquals( singletonList( "-" ), options.valuesOf( "o" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ToStringTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ToStringTest.java new file mode 100644 index 0000000000..0b01a789bb --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ToStringTest.java @@ -0,0 +1,73 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.Collection; + +import static com.google.common.collect.Lists.newArrayList; +import static java.util.Arrays.*; + +import joptsimple.util.KeyValuePair; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +@RunWith( Parameterized.class ) +public class ToStringTest { + private final Object subject; + private final String[] substrings; + + public ToStringTest( Object subject, String[] substrings ) { + this.subject = subject; + this.substrings = substrings.clone(); + } + + @Parameterized.Parameters + public static Collection<?> objectsAndStringRepresentations() { + return asList( new Object[][] { + { KeyValuePair.valueOf( "key=value" ), new String[] { "key", "=", "value" } }, + { new UnrecognizedOptionException( "a" ), new String[] { "a" } }, + { new NoArgumentOptionSpec( asList( "a", "b" ), "" ), new String[] { "[a, b]" } }, + { new UnavailableOptionException( + newArrayList( new NoArgumentOptionSpec( "a" ), new NoArgumentOptionSpec( "b" ) ) ), + new String[] { "[a, b]" } }, + } ); + } + + @Test + public void givesUsefulStringRepresentations() { + String stringRepresentation = subject.toString(); + + for ( String each : substrings ) + assertThat( stringRepresentation, containsString( each ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/TypesafeOptionArgumentRetrievalTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/TypesafeOptionArgumentRetrievalTest.java new file mode 100644 index 0000000000..cea1e728a1 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/TypesafeOptionArgumentRetrievalTest.java @@ -0,0 +1,317 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.util.List; + +import org.junit.Test; + +import static java.lang.Short.*; +import static java.util.Arrays.*; +import static java.util.Collections.*; +import static joptsimple.ExceptionMatchers.*; +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class TypesafeOptionArgumentRetrievalTest extends AbstractOptionParserFixture { + @Test + public void retrievalOfTypedRequiredArgumentsInATypesafeManner() { + OptionSpec<Integer> optionA = parser.accepts( "a" ).withRequiredArg().ofType( Integer.class ); + + OptionSet options = parser.parse( "-a", "1" ); + + assertTrue( options.has( optionA ) ); + Integer valueFromOption = optionA.value( options ); + assertEquals( Integer.valueOf( 1 ), valueFromOption ); + Integer valueFromOptionSet = options.valueOf( optionA ); + assertEquals( valueFromOption, valueFromOptionSet ); + + List<Integer> valuesFromOption = optionA.values( options ); + assertEquals( asList( 1 ), valuesFromOption ); + List<Integer> valuesFromOptionSet = options.valuesOf( optionA ); + assertEquals( valuesFromOption, valuesFromOptionSet ); + } + + @Test + public void retrievalOfTypedOptionalArgumentsInATypesafeManner() { + OptionSpec<Double> optionB = parser.accepts( "b" ).withOptionalArg().ofType( Double.class ); + + OptionSet options = parser.parse( "-b", "3.14D" ); + + assertTrue( options.has( optionB ) ); + assertEquals( Double.valueOf( 3.14D ), optionB.value( options ) ); + assertEquals( asList( 3.14D ), optionB.values( options ) ); + } + + @Test + public void retrievalOfUntypedRequiredArgumentsInATypesafeManner() { + OptionSpec<String> optionC = parser.accepts( "c" ).withRequiredArg(); + + OptionSet options = parser.parse( "-c", "foo", "-c", "bar" ); + + assertTrue( options.has( optionC ) ); + assertEquals( asList( "foo", "bar" ), optionC.values( options ) ); + } + + @Test + public void retrievalOfUntypedOptionalArgumentsInATypesafeManner() { + OptionSpec<String> optionD = parser.accepts( "d" ).withRequiredArg(); + + OptionSet options = parser.parse( "-d", "foo", "-d", "bar", "-d", "baz" ); + + assertTrue( options.has( optionD ) ); + List<String> valuesFromOption = optionD.values( options ); + assertEquals( asList( "foo", "bar", "baz" ), valuesFromOption ); + List<String> valuesFromOptionSet = options.valuesOf( optionD ); + assertEquals( valuesFromOption, valuesFromOptionSet ); + } + + @Test + public void retrievalWithVoidOption() { + OptionSpec<Void> optionE = parser.accepts( "e" ); + + OptionSet options = parser.parse( "-e" ); + + assertTrue( options.has( optionE ) ); + assertEquals( emptyList(), options.valuesOf( optionE ) ); + } + + @Test + public void primitiveBooleanAllowedAsTypeSpecifier() { + OptionSpec<Boolean> optionA = parser.accepts( "a" ).withRequiredArg().ofType( boolean.class ); + + OptionSet options = parser.parse( "-a", "false" ); + + assertTrue( options.has( optionA ) ); + assertEquals( asList( false ), options.valuesOf( optionA ) ); + } + + @Test + public void primitiveByteAllowedAsTypeSpecifier() { + OptionSpec<Byte> optionB = parser.accepts( "b" ).withOptionalArg().ofType( byte.class ); + + OptionSet options = parser.parse( "-b", "3" ); + + assertTrue( options.has( optionB ) ); + assertEquals( asList( Byte.valueOf( "3" ) ), options.valuesOf( optionB ) ); + } + + @Test( expected = IllegalArgumentException.class ) + public void primitiveCharAllowedAsTypeSpecifier() { + parser.accepts( "c" ).withRequiredArg().ofType( char.class ); + } + + @Test + public void primitiveDoubleAllowedAsTypeSpecifier() { + OptionSpec<Double> optionD = parser.accepts( "d" ).withOptionalArg().ofType( double.class ); + + OptionSet options = parser.parse( "-d", "3.1" ); + + assertTrue( options.has( optionD ) ); + assertEquals( asList( 3.1D ), options.valuesOf( optionD ) ); + } + + @Test + public void primitiveFloatAllowedAsTypeSpecifier() { + OptionSpec<Float> optionE = parser.accepts( "e" ).withRequiredArg().ofType( float.class ); + + OptionSet options = parser.parse( "-e", "2.09" ); + + assertTrue( options.has( optionE ) ); + assertEquals( asList( 2.09F ), options.valuesOf( optionE ) ); + } + + @Test + public void primitiveIntAllowedAsTypeSpecifier() { + OptionSpec<Integer> optionF = parser.accepts( "F" ).withRequiredArg().ofType( int.class ); + + OptionSet options = parser.parse( "-F", "91" ); + + assertTrue( options.has( optionF ) ); + assertEquals( asList( 91 ), options.valuesOf( optionF ) ); + } + + @Test + public void primitiveLongAllowedAsTypeSpecifier() { + OptionSpec<Long> optionG = parser.accepts( "g" ).withOptionalArg().ofType( long.class ); + + OptionSet options = parser.parse("-g", "12"); + + assertTrue( options.has( optionG ) ); + assertEquals( asList( 12L ), options.valuesOf( optionG ) ); + } + + @Test + public void primitiveShortAllowedAsTypeSpecifier() { + OptionSpec<Short> optionH = parser.accepts( "H" ).withRequiredArg().ofType( short.class ); + + OptionSet options = parser.parse( "-H", "8" ); + + assertTrue( options.has( optionH ) ); + assertEquals( asList( Short.valueOf( "8" ) ), options.valuesOf( optionH ) ); + } + + @Test + public void cannotFoolHasWithAnOptionNotIssuedFromBuilder() { + parser.accepts( "e" ); + + OptionSet options = parser.parse( "-e" ); + + assertFalse( options.has( new FakeOptionSpec<Void>( "e" ) ) ); + } + + @Test + public void cannotFoolHasArgumentWithAnOptionNotIssuedFromBuilder() { + parser.accepts( "f" ).withRequiredArg(); + OptionSpec<String> fakeOptionF = new FakeOptionSpec<>( "f" ); + + OptionSet options = parser.parse( "-f", "boo" ); + + assertFalse( options.hasArgument( fakeOptionF ) ); + } + + @Test + public void cannotFoolValueOfWithAnOptionNotIssuedFromBuilder() { + parser.accepts( "g" ).withRequiredArg(); + + OptionSet options = parser.parse( "-g", "foo" ); + + assertNull( options.valueOf( new FakeOptionSpec<String>( "g" ) ) ); + } + + @Test + public void cannotFoolValuesOfWithAnOptionNotIssuedFromBuilder() { + parser.accepts( "h" ).withRequiredArg(); + + OptionSet options = parser.parse( "-h", "foo", "-h", "bar" ); + + assertEquals( emptyList(), options.valuesOf( new FakeOptionSpec<String>( "h" ) ) ); + } + + @Test( expected = ClassCastException.class ) + public void canSubvertTypeSafetyIfYouUseAnOptionSpecAsTheWrongType() { + ArgumentAcceptingOptionSpec<String> optionI = parser.accepts( "i" ).withRequiredArg(); + optionI.ofType( Integer.class ); + + OptionSet options = parser.parse( "-i", "2" ); + + @SuppressWarnings( "unused" ) + String value = optionI.value( options ); + } + + @Test( expected = ClassCastException.class ) + public void canSubvertTypeSafetyIfYouGiveAnOptionSpecToOptionSetAsTheWrongType() { + ArgumentAcceptingOptionSpec<String> optionJ = parser.accepts( "j" ).withRequiredArg(); + optionJ.ofType( Integer.class ); + + OptionSet options = parser.parse( "-j", "3" ); + + @SuppressWarnings( "unused" ) + String value = options.valuesOf( optionJ ).get( 0 ); + } + + @Test + public void canUseBooleanType() { + OptionSpec<Boolean> optionK = parser.accepts( "k" ).withRequiredArg().ofType( Boolean.class ); + + OptionSet options = parser.parse( "-k", "true" ); + + assertTrue( optionK.value( options ) ); + } + + @Test + public void usesConverterIfProvided() { + OptionSpec<Short> optionL = parser.accepts( "L" ).withRequiredArg().withValuesConvertedBy( + new ValueConverter<Short>() { + public Short convert( String value ) { + return parseShort( value ); + } + + public Class<Short> valueType() { + return Short.class; + } + + public String valuePattern() { + return null; + } + } ); + + OptionSet options = parser.parse( "-L", "34" ); + + assertEquals( new Short( (short) 34 ), optionL.value( options ) ); + } + + @Test + public void wrapsValueConversionExceptionsRaisedByConverter() { + OptionSpec<Character> optionM = parser.accepts( "m" ).withRequiredArg().withValuesConvertedBy( + new ValueConverter<Character>() { + public Character convert( String value ) { + throw new ValueConversionException( value ); + } + + public Class<Character> valueType() { + return Character.class; + } + + public String valuePattern() { + return null; + } + } ); + + OptionSet options = parser.parse( "-m", "a" ); + + thrown.expect( OptionArgumentConversionException.class ); + thrown.expect( withCauseOfType( ValueConversionException.class ) ); + + optionM.value( options ); + } + + private static class FakeOptionSpec<V> implements OptionSpec<V> { + private final String option; + + FakeOptionSpec( String option ) { + this.option = option; + } + + public List<String> options() { + return asList( option ); + } + + public V value( OptionSet detectedOptions ) { + return detectedOptions.valueOf( this ); + } + + public List<V> values( OptionSet detectedOptions ) { + return detectedOptions.valuesOf( this ); + } + + public boolean isForHelp() { + return false; + } + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/UtilityClassesUninstantiabilityHarness.java b/third_party/java/jopt-simple/src/test/java/joptsimple/UtilityClassesUninstantiabilityHarness.java new file mode 100644 index 0000000000..e70dba7135 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/UtilityClassesUninstantiabilityHarness.java @@ -0,0 +1,60 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static joptsimple.ExceptionMatchers.*; +import static org.junit.rules.ExpectedException.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public abstract class UtilityClassesUninstantiabilityHarness { + @Rule public final ExpectedException thrown = none(); + + private final Class<?> utility; + + protected UtilityClassesUninstantiabilityHarness( Class<?> utility ) { + this.utility = utility; + } + + @Test + public final void attemptToInstantiate() throws Exception { + Constructor<?> constructor = utility.getDeclaredConstructor(); + constructor.setAccessible( true ); + + thrown.expect( InvocationTargetException.class ); + thrown.expect( withTargetOfType( UnsupportedOperationException.class ) ); + + constructor.newInstance(); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ValueConverterAdmitsSubclassesOfValueTypeTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ValueConverterAdmitsSubclassesOfValueTypeTest.java new file mode 100644 index 0000000000..a7e726ed91 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ValueConverterAdmitsSubclassesOfValueTypeTest.java @@ -0,0 +1,63 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class ValueConverterAdmitsSubclassesOfValueTypeTest { + @Test + public void subclassOfValueType() { + ValueConverter<List<String>> converter = new ValueConverter<List<String>>() { + public List<String> convert( String value ) { + return Collections.singletonList( value ); + } + + public Class<? extends List<String>> valueType() { + return ListOfStrings.class; + } + + public String valuePattern() { + return null; + } + }; + + assertEquals( Arrays.asList( "foo" ), converter.convert( "foo" ) ); + } + + static class ListOfStrings extends ArrayList<String> { + private static final long serialVersionUID = 1L; + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/ValueOfHaver.java b/third_party/java/jopt-simple/src/test/java/joptsimple/ValueOfHaver.java new file mode 100644 index 0000000000..a3092601d8 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/ValueOfHaver.java @@ -0,0 +1,39 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class ValueOfHaver { + private ValueOfHaver() { + // no-op + } + + public static ValueOfHaver valueOf( String s ) { + return null; + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/WAsAbbreviationForLongOptionTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/WAsAbbreviationForLongOptionTest.java new file mode 100644 index 0000000000..119c14b810 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/WAsAbbreviationForLongOptionTest.java @@ -0,0 +1,64 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Collections.*; + +import org.junit.Before; +import org.junit.Test; + +import static joptsimple.ExceptionMatchers.*; +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class WAsAbbreviationForLongOptionTest extends AbstractOptionParserFixture { + @Before + public final void initializeParser() { + parser.accepts( "Wally" ).withRequiredArg(); + } + + @Test + public void abbreviation() { + OptionSet options = parser.parse( "--W", "silent" ); + + assertOptionDetected( options, "Wally" ); + assertOptionNotDetected( options, "W" ); + assertEquals( singletonList( "silent" ), options.valuesOf( "Wally" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void recognizeLongOptionsTrumpsLongOptionAbbreviation() { + parser.recognizeAlternativeLongOptions( true ); + + thrown.expect( UnrecognizedOptionException.class ); + thrown.expect( withOption( "silent" ) ); + + parser.parse( "--W", "silent" ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/WAsShortOptionTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/WAsShortOptionTest.java new file mode 100644 index 0000000000..8cfb5231ae --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/WAsShortOptionTest.java @@ -0,0 +1,63 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Collections.*; + +import org.junit.Before; +import org.junit.Test; + +import static joptsimple.ExceptionMatchers.*; +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class WAsShortOptionTest extends AbstractOptionParserFixture { + @Before + public final void initializeParser() { + parser.accepts( "W" ); + } + + @Test + public void wIsLegal() { + OptionSet options = parser.parse( "-W", "silent" ); + + assertOptionDetected( options, "W" ); + assertEquals( emptyList(), options.valuesOf( "W" ) ); + assertEquals( singletonList( "silent" ), options.nonOptionArguments() ); + } + + @Test + public void recognizeLongOptionsTrumpsShortOptionW() { + parser.recognizeAlternativeLongOptions( true ); + + thrown.expect( UnrecognizedOptionException.class ); + thrown.expect( withOption( "silent" ) ); + + parser.parse( "-W", "silent" ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/WExtensionNoArgumentTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/WExtensionNoArgumentTest.java new file mode 100644 index 0000000000..cb8a5e93ef --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/WExtensionNoArgumentTest.java @@ -0,0 +1,65 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Collections.*; + +import org.junit.Before; +import org.junit.Test; + +import static joptsimple.ExceptionMatchers.*; +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class WExtensionNoArgumentTest extends AbstractOptionParserFixture { + @Before + public final void initializeParser() { + parser.accepts( "silent" ); + parser.recognizeAlternativeLongOptions( true ); + } + + @Test + public void turnOffWExtension() { + parser.recognizeAlternativeLongOptions( false ); + + thrown.expect( UnrecognizedOptionException.class ); + thrown.expect( withOption( "W" ) ); + + parser.parse( "-W", "silent" ); + } + + @Test + public void wExtensionWithLongOptionWithoutAnArgument() { + OptionSet options = parser.parse( "-W", "silent" ); + + assertOptionNotDetected( options, "W" ); + assertOptionDetected( options, "silent" ); + assertEquals( emptyList(), options.valuesOf( "silent" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/WExtensionWithArgumentTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/WExtensionWithArgumentTest.java new file mode 100644 index 0000000000..76f247a3a3 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/WExtensionWithArgumentTest.java @@ -0,0 +1,116 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple; + +import static java.util.Collections.*; + +import org.junit.Before; +import org.junit.Test; + +import static joptsimple.ExceptionMatchers.*; +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class WExtensionWithArgumentTest extends AbstractOptionParserFixture { + @Before + public final void initializeParser() { + parser.recognizeAlternativeLongOptions( true ); + parser.accepts( "silent" ).withOptionalArg(); + } + + @Test + public void separateArgument() { + OptionSet options = parser.parse( "-W", "silent", "4" ); + + assertOptionNotDetected( options, "W" ); + assertOptionDetected( options, "silent" ); + assertEquals( singletonList( "4" ), options.valuesOf( "silent" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void togetherArgument() { + OptionSet options = parser.parse( "-W", "silent=6" ); + + assertOptionNotDetected( options, "W" ); + assertOptionDetected( options, "silent" ); + assertEquals( singletonList( "6" ), options.valuesOf( "silent" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void abbreviationWithTogetherArgument() { + OptionSet options = parser.parse( "-W", "s=6" ); + + assertOptionNotDetected( options, "W" ); + assertOptionDetected( options, "silent" ); + assertOptionNotDetected( options, "s" ); + assertEquals( singletonList( "6" ), options.valuesOf( "silent" ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void illegalLongOption() { + thrown.expect( UnrecognizedOptionException.class ); + thrown.expect( withOption( "foo" ) ); + + parser.parse( "-W", "foo=bar" ); + } + + @Test + public void noMoreArguments() { + thrown.expect( OptionMissingRequiredArgumentException.class ); + thrown.expect( withOption( "W" ) ); + + parser.parse( "-W" ); + } + + @Test + public void typedTogetherArg() { + OptionSpec<Integer> level = parser.accepts( "level" ).withRequiredArg().ofType( Integer.class ); + + OptionSet options = parser.parse( "-W", "level=4" ); + + assertOptionNotDetected( options, "W" ); + assertOptionDetected( options, "level" ); + assertEquals( singletonList( 4 ), options.valuesOf( level ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } + + @Test + public void typedSeparateArg() { + OptionSpec<Integer> floor = parser.accepts( "floor" ).withRequiredArg().ofType( Integer.class ); + + OptionSet options = parser.parse( "-W", "floor", "5" ); + + assertOptionNotDetected( options, "W" ); + assertOptionDetected( options, "floor" ); + assertEquals( singletonList( 5 ), options.valuesOf( floor ) ); + assertEquals( emptyList(), options.nonOptionArguments() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/AlternativeLongOptionsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/AlternativeLongOptionsTest.java new file mode 100644 index 0000000000..3657a40eab --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/AlternativeLongOptionsTest.java @@ -0,0 +1,22 @@ +package joptsimple.examples; + +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class AlternativeLongOptionsTest { + @Test + public void handlesAlternativeLongOptions() { + OptionParser parser = new OptionParser( "W;" ); + parser.recognizeAlternativeLongOptions( true ); // same effect as above + parser.accepts( "level" ).withRequiredArg(); + + OptionSet options = parser.parse( "-W", "level=5" ); + + assertTrue( options.has( "level" ) ); + assertTrue( options.hasArgument( "level" ) ); + assertEquals( "5", options.valueOf( "level" ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/DefaultValuesForOptionArgumentsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/DefaultValuesForOptionArgumentsTest.java new file mode 100644 index 0000000000..cd11f07b63 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/DefaultValuesForOptionArgumentsTest.java @@ -0,0 +1,58 @@ +package joptsimple.examples; + +import java.io.File; + +import joptsimple.OptionException; +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import joptsimple.OptionSpec; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static joptsimple.examples.Level.*; +import static org.junit.Assert.*; +import static org.junit.rules.ExpectedException.*; + +public class DefaultValuesForOptionArgumentsTest { + @Rule public final ExpectedException thrown = none(); + + @Test + public void allowsSpecificationOfDefaultValues() throws Exception { + File tempDir = new File( System.getProperty( "java.io.tmpdir" ) ); + File tempFile = File.createTempFile( "aFile", ".txt" ); + OptionParser parser = new OptionParser(); + OptionSpec<File> infile = + parser.accepts( "infile" ).withRequiredArg().ofType( File.class ).defaultsTo( tempFile ); + OptionSpec<File> outdir = + parser.accepts( "outdir" ).withRequiredArg().ofType( File.class ).defaultsTo( tempDir ); + OptionSpec<Integer> bufferSize = + parser.accepts( "buffer-size" ).withOptionalArg().ofType( Integer.class ).defaultsTo( 4096 ); + OptionSpec<Level> level = + parser.accepts( "level" ).withOptionalArg().ofType( Level.class ).defaultsTo( INFO ); + OptionSpec<Integer> count = + parser.accepts( "count" ).withOptionalArg().ofType( Integer.class ).defaultsTo( 10 ); + + OptionSet options = parser.parse( "--level", "WARNING", "--count", "--infile", "/etc/passwd" ); + + assertEquals( new File( "/etc/passwd" ), infile.value( options ) ); + assertTrue( options.has( infile ) ); + assertTrue( options.hasArgument( infile ) ); + assertEquals( tempDir, outdir.value( options ) ); + assertFalse( options.has( outdir ) ); + assertFalse( options.hasArgument( outdir ) ); + assertEquals( Integer.valueOf( 4096 ), bufferSize.value( options ) ); + assertFalse( options.has( bufferSize ) ); + assertFalse( options.hasArgument( bufferSize ) ); + assertEquals( WARNING, level.value( options ) ); + assertTrue( options.has( level ) ); + assertTrue( options.hasArgument( level ) ); + assertEquals( Integer.valueOf( 10 ), count.value( options ) ); + assertTrue( options.has( count ) ); + assertFalse( options.hasArgument( count ) ); + + thrown.expect( OptionException.class ); + + parser.parse( "--outdir" ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ExceptionExample.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ExceptionExample.java new file mode 100644 index 0000000000..fb4a9e723a --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ExceptionExample.java @@ -0,0 +1,11 @@ +package joptsimple.examples; + +import joptsimple.OptionParser; + +public class ExceptionExample { + public static void main( String[] args ) { + OptionParser parser = new OptionParser(); + + parser.parse( "-x" ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ExportOptionsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ExportOptionsTest.java new file mode 100644 index 0000000000..730e31834c --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ExportOptionsTest.java @@ -0,0 +1,61 @@ +package joptsimple.examples; + +import com.google.common.base.Joiner; +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import joptsimple.OptionSpec; +import org.junit.Test; + +import java.io.File; +import java.util.List; +import java.util.Map.Entry; +import java.util.Properties; + +import static org.junit.Assert.assertEquals; + +public class ExportOptionsTest { + private static Properties asProperties( OptionSet options, String prefix ) { + Properties properties = new Properties(); + for ( Entry<OptionSpec<?>, List<?>> entry : options.asMap().entrySet() ) { + OptionSpec<?> spec = entry.getKey(); + properties.setProperty( + asPropertyKey( prefix, spec ), + asPropertyValue( entry.getValue(), options.has( spec ) ) ); + } + return properties; + } + + private static String asPropertyKey( String prefix, OptionSpec<?> spec ) { + List<String> flags = spec.options(); + for ( String flag : flags ) + if ( 1 < flag.length() ) + return null == prefix ? flag : ( prefix + '.' + flag ); + throw new IllegalArgumentException( "No usable non-short flag: " + flags ); + } + + private static String asPropertyValue( List<?> values, boolean present ) { + // Simple flags have no values; treat presence/absence as true/false + return values.isEmpty() ? String.valueOf( present ) : Joiner.on( "," ).join( values ); + } + + @Test + public void allowsExportOfOptions() { + Properties expected = new Properties(); + expected.setProperty( "rice.count", "3" ); + // Cannot check path as string directly - Windows flips the leading slash + expected.setProperty( "rice.output-dir", new File( "/tmp" ).toString() ); + expected.setProperty( "rice.fun", "false" ); + expected.setProperty( "rice.verbose", "true" ); + + OptionParser parser = new OptionParser(); + OptionSpec<Integer> count = parser.accepts( "count" ).withRequiredArg().ofType( Integer.class ); + OptionSpec<File> outputDir = parser.accepts( "output-dir" ).withOptionalArg().ofType( File.class ); + OptionSpec<Void> verbose = parser.accepts( "verbose" ); + OptionSpec<Void> fun = parser.accepts( "fun" ); + OptionSpec<File> files = parser.nonOptions().ofType( File.class ); + + OptionSet options = parser.parse( "--count", "3", "--output-dir", "/tmp", "--verbose", "a.txt", "b.txt" ); + + assertEquals( expected, asProperties( options, "rice" ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/HelpFormatterExample.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/HelpFormatterExample.java new file mode 100644 index 0000000000..0262d2a76a --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/HelpFormatterExample.java @@ -0,0 +1,69 @@ +package joptsimple.examples; + +import java.io.File; +import java.util.HashSet; +import java.util.Map; + +import static java.io.File.*; +import static java.util.Arrays.*; + +import joptsimple.HelpFormatter; +import joptsimple.OptionDescriptor; +import joptsimple.OptionParser; + +import static joptsimple.util.DateConverter.*; + +public class HelpFormatterExample { + static class MyFormatter implements HelpFormatter { + public String format( Map<String, ? extends OptionDescriptor> options ) { + StringBuilder buffer = new StringBuilder(); + for ( OptionDescriptor each : new HashSet<>( options.values() ) ) { + buffer.append( lineFor( each ) ); + } + return buffer.toString(); + } + + private String lineFor( OptionDescriptor descriptor ) { + if ( descriptor.representsNonOptions() ) { + return descriptor.argumentDescription() + '(' + descriptor.argumentTypeIndicator() + "): " + + descriptor.description() + System.getProperty( "line.separator" ); + } + + StringBuilder line = new StringBuilder( descriptor.options().toString() ); + line.append( ": description = " ).append( descriptor.description() ); + line.append( ", required = " ).append( descriptor.isRequired() ); + line.append( ", accepts arguments = " ).append( descriptor.acceptsArguments() ); + line.append( ", requires argument = " ).append( descriptor.requiresArgument() ); + line.append( ", argument description = " ).append( descriptor.argumentDescription() ); + line.append( ", argument type indicator = " ).append( descriptor.argumentTypeIndicator() ); + line.append( ", default values = " ).append( descriptor.defaultValues() ); + line.append( System.getProperty( "line.separator" ) ); + return line.toString(); + } + } + + public static void main( String[] args ) throws Exception { + OptionParser parser = new OptionParser() { + { + accepts( "c" ).withRequiredArg().ofType( Integer.class ) + .describedAs( "count" ).defaultsTo( 1 ); + accepts( "q" ).withOptionalArg().ofType( Double.class ) + .describedAs( "quantity" ); + accepts( "d", "some date" ).withRequiredArg().required() + .withValuesConvertedBy( datePattern( "MM/dd/yy" ) ); + acceptsAll( asList( "v", "talkative", "chatty" ), "be more verbose" ); + accepts( "output-file" ).withOptionalArg().ofType( File.class ) + .describedAs( "file" ); + acceptsAll( asList( "h", "?" ), "show help" ).forHelp(); + acceptsAll( asList( "cp", "classpath" ) ).withRequiredArg() + .describedAs( "path1" + pathSeparatorChar + "path2:..." ) + .ofType( File.class ) + .withValuesSeparatedBy( pathSeparatorChar ); + nonOptions( "files to chew on" ).ofType( File.class ).describedAs( "input files" ); + } + }; + + parser.formatHelpWith( new MyFormatter() ); + parser.printHelpOn( System.out ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/HelpScreenExample.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/HelpScreenExample.java new file mode 100644 index 0000000000..44f024b793 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/HelpScreenExample.java @@ -0,0 +1,35 @@ +package joptsimple.examples; + +import java.io.File; + +import static java.io.File.*; +import static java.util.Arrays.*; + +import joptsimple.OptionParser; + +import static joptsimple.util.DateConverter.*; + +public class HelpScreenExample { + public static void main( String[] args ) throws Exception { + OptionParser parser = new OptionParser() { + { + accepts( "c" ).withRequiredArg().ofType( Integer.class ) + .describedAs( "count" ).defaultsTo( 1 ); + accepts( "q" ).withOptionalArg().ofType( Double.class ) + .describedAs( "quantity" ); + accepts( "d", "some date" ).withRequiredArg().required() + .withValuesConvertedBy( datePattern( "MM/dd/yy" ) ); + acceptsAll( asList( "v", "talkative", "chatty" ), "be more verbose" ); + accepts( "output-file" ).withOptionalArg().ofType( File.class ) + .describedAs( "file" ); + acceptsAll( asList( "h", "?" ), "show help" ).forHelp(); + acceptsAll( asList( "cp", "classpath" ) ).withRequiredArg() + .describedAs( "path1" + pathSeparatorChar + "path2:..." ) + .ofType( File.class ) + .withValuesSeparatedBy( pathSeparatorChar ); + } + }; + + parser.printHelpOn( System.out ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/Level.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/Level.java new file mode 100644 index 0000000000..b3d95d4e58 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/Level.java @@ -0,0 +1,7 @@ +package joptsimple.examples; + +public enum Level { + WARNING, + INFO, + DEBUG +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/LongOptionsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/LongOptionsTest.java new file mode 100644 index 0000000000..30fac0c4d1 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/LongOptionsTest.java @@ -0,0 +1,21 @@ +package joptsimple.examples; + +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class LongOptionsTest { + @Test + public void acceptsLongOptions() { + OptionParser parser = new OptionParser(); + parser.accepts( "flag" ); + parser.accepts( "verbose" ); + + OptionSet options = parser.parse( "--flag" ); + + assertTrue( options.has( "flag" ) ); + assertFalse( options.has( "verbose" ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/LongOptionsWithArgumentPositioningTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/LongOptionsWithArgumentPositioningTest.java new file mode 100644 index 0000000000..1cf018b867 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/LongOptionsWithArgumentPositioningTest.java @@ -0,0 +1,26 @@ +package joptsimple.examples; + +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class LongOptionsWithArgumentPositioningTest { + @Test + public void allowsDifferentFormsOfPairingArgumentWithOption() { + OptionParser parser = new OptionParser(); + parser.accepts( "count" ).withRequiredArg(); + parser.accepts( "level" ).withOptionalArg(); + + OptionSet options = parser.parse( "--count", "4", "--level=3" ); + + assertTrue( options.has( "count" ) ); + assertTrue( options.hasArgument( "count" ) ); + assertEquals( "4", options.valueOf( "count" ) ); + + assertTrue( options.has( "level" ) ); + assertTrue( options.hasArgument( "level" ) ); + assertEquals( "3", options.valueOf( "level" ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/LongOptionsWithArgumentsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/LongOptionsWithArgumentsTest.java new file mode 100644 index 0000000000..38ef67cfec --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/LongOptionsWithArgumentsTest.java @@ -0,0 +1,34 @@ +package joptsimple.examples; + +import static java.util.Arrays.*; +import static java.util.Collections.*; + +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class LongOptionsWithArgumentsTest { + @Test + public void supportsLongOptionsWithArgumentsAndAbbreviations() { + OptionParser parser = new OptionParser(); + parser.accepts( "flag" ); + parser.accepts( "count" ).withRequiredArg(); + parser.accepts( "level" ).withOptionalArg(); + + OptionSet options = parser.parse( "-flag", "--co", "3", "--lev" ); + + assertTrue( options.has( "flag" ) ); + + assertTrue( options.has( "count" ) ); + assertTrue( options.hasArgument( "count" ) ); + assertEquals( "3", options.valueOf( "count" ) ); + assertEquals( asList( "3" ), options.valuesOf( "count" ) ); + + assertTrue( options.has( "level" ) ); + assertFalse( options.hasArgument( "level" ) ); + assertNull( options.valueOf( "level" ) ); + assertEquals( emptyList(), options.valuesOf( "level" ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/MultipleDelimitedArgumentsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/MultipleDelimitedArgumentsTest.java new file mode 100644 index 0000000000..47eefd066e --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/MultipleDelimitedArgumentsTest.java @@ -0,0 +1,29 @@ +package joptsimple.examples; + +import java.io.File; + +import static java.io.File.*; +import static java.util.Arrays.*; + +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import joptsimple.OptionSpec; +import org.junit.Test; + +import static joptsimple.examples.Strings.*; +import static org.junit.Assert.*; + +public class MultipleDelimitedArgumentsTest { + @Test + public void supportsMultipleDelimitedArguments() { + OptionParser parser = new OptionParser(); + OptionSpec<File> path = parser.accepts( "path" ).withRequiredArg().ofType( File.class ) + .withValuesSeparatedBy( pathSeparatorChar ); + + OptionSet options = parser.parse( "--path", join( pathSeparatorChar, "/tmp", "/var", "/opt" ) ); + + assertTrue( options.has( path ) ); + assertTrue( options.hasArgument( path ) ); + assertEquals( asList( new File( "/tmp" ), new File( "/var" ), new File( "/opt" ) ), options.valuesOf( path ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/OptionArgumentConverterTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/OptionArgumentConverterTest.java new file mode 100644 index 0000000000..5841794d83 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/OptionArgumentConverterTest.java @@ -0,0 +1,49 @@ +/* + The MIT License + + Copyright (c) 2004-2014 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.examples; + +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import org.joda.time.LocalDate; +import org.junit.Test; + +import static joptsimple.util.DateConverter.*; +import static joptsimple.util.RegexMatcher.*; +import static org.junit.Assert.*; + +public class OptionArgumentConverterTest { + @Test + public void usesConvertersOnOptionArgumentsWhenTold() { + OptionParser parser = new OptionParser(); + parser.accepts( "birthdate" ).withRequiredArg().withValuesConvertedBy( datePattern( "MM/dd/yy" ) ); + parser.accepts( "ssn" ).withRequiredArg().withValuesConvertedBy( regex( "\\d{3}-\\d{2}-\\d{4}" )); + + OptionSet options = parser.parse( "--birthdate", "02/24/05", "--ssn", "123-45-6789" ); + + assertEquals( new LocalDate( 2005, 2, 24 ).toDate(), options.valueOf( "birthdate" ) ); + assertEquals( "123-45-6789", options.valueOf( "ssn" ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/OptionArgumentValueTypeTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/OptionArgumentValueTypeTest.java new file mode 100644 index 0000000000..2f8e51c630 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/OptionArgumentValueTypeTest.java @@ -0,0 +1,27 @@ +package joptsimple.examples; + +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class OptionArgumentValueTypeTest { + @Test + public void convertsArgumentsToJavaValueTypes() { + OptionParser parser = new OptionParser(); + parser.accepts( "flag" ); + parser.accepts( "count" ).withRequiredArg().ofType( Integer.class ); + parser.accepts( "level" ).withOptionalArg().ofType( Level.class ); + + OptionSet options = parser.parse( "--count", "3", "--level", "DEBUG" ); + + assertTrue( options.has( "count" ) ); + assertTrue( options.hasArgument( "count" ) ); + assertEquals( 3, options.valueOf( "count" ) ); + + assertTrue( options.has( "level" ) ); + assertTrue( options.hasArgument( "level" ) ); + assertEquals( Level.DEBUG, options.valueOf( "level" ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/OptionSynonymTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/OptionSynonymTest.java new file mode 100644 index 0000000000..336c4d005c --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/OptionSynonymTest.java @@ -0,0 +1,30 @@ +package joptsimple.examples; + +import java.util.List; + +import static java.util.Arrays.*; + +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class OptionSynonymTest { + @Test + public void supportsOptionSynonyms() { + OptionParser parser = new OptionParser(); + List<String> synonyms = asList( "message", "blurb", "greeting" ); + parser.acceptsAll( synonyms ).withRequiredArg(); + String expectedMessage = "Hello"; + + OptionSet options = parser.parse( "--message", expectedMessage ); + + for ( String each : synonyms ) { + assertTrue( each, options.has( each ) ); + assertTrue( each, options.hasArgument( each ) ); + assertEquals( each, expectedMessage, options.valueOf( each ) ); + assertEquals( each, asList( expectedMessage ), options.valuesOf( each ) ); + } + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/PosixlyCorrectTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/PosixlyCorrectTest.java new file mode 100644 index 0000000000..7acb957a77 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/PosixlyCorrectTest.java @@ -0,0 +1,37 @@ +package joptsimple.examples; + +import static java.util.Arrays.*; +import static java.util.Collections.*; + +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class PosixlyCorrectTest { + @Test + public void supportsPosixlyCorrectBehavior() { + OptionParser parser = new OptionParser( "i:j::k" ); + String[] arguments = { "-ibar", "-i", "junk", "xyz", "-jixnay", "foo", "-k", "blah", "--", "bah" }; + + OptionSet options = parser.parse( arguments ); + + assertTrue( options.has( "i" ) ); + assertTrue( options.has( "j" ) ); + assertTrue( options.has( "k" ) ); + assertEquals( asList( "bar", "junk" ), options.valuesOf( "i" ) ); + assertEquals( asList( "ixnay" ), options.valuesOf( "j" ) ); + assertEquals( asList( "xyz", "foo", "blah", "bah" ), options.nonOptionArguments() ); + + parser.posixlyCorrect( true ); + options = parser.parse( arguments ); + + assertTrue( options.has( "i" ) ); + assertFalse( options.has( "j" ) ); + assertFalse( options.has( "k" ) ); + assertEquals( asList( "bar", "junk" ), options.valuesOf( "i" ) ); + assertEquals( emptyList(), options.valuesOf( "j" ) ); + assertEquals( asList( "xyz", "-jixnay", "foo", "-k", "blah", "--", "bah" ), options.nonOptionArguments() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/RequiredIfExample.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/RequiredIfExample.java new file mode 100644 index 0000000000..c062fff87e --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/RequiredIfExample.java @@ -0,0 +1,14 @@ +package joptsimple.examples; + +import joptsimple.OptionParser; + +public class RequiredIfExample { + public static void main( String[] args ) { + OptionParser parser = new OptionParser(); + parser.accepts( "ftp" ); + parser.accepts( "username" ).requiredIf( "ftp" ).withRequiredArg(); + parser.accepts( "password" ).requiredIf( "ftp" ).withRequiredArg(); + + parser.parse( "--ftp" ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/RequiredOptionsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/RequiredOptionsTest.java new file mode 100644 index 0000000000..5a40ea2ed9 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/RequiredOptionsTest.java @@ -0,0 +1,49 @@ +package joptsimple.examples; + +import joptsimple.OptionException; +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class RequiredOptionsTest { + @Test( expected = OptionException.class ) + public void allowsSpecificationOfRequiredOptions() { + OptionParser parser = new OptionParser() { + { + accepts( "userid" ).withRequiredArg().required(); + accepts( "password" ).withRequiredArg().required(); + } + }; + + parser.parse( "--userid", "bob" ); + } + + @Test + public void aHelpOptionMeansRequiredOptionsNeedNotBePresent() { + OptionParser parser = new OptionParser() { + { + accepts( "userid" ).withRequiredArg().required(); + accepts( "password" ).withRequiredArg().required(); + accepts( "help" ).forHelp(); + } + }; + + OptionSet options = parser.parse( "--help" ); + assertTrue( options.has( "help" ) ); + } + + @Test( expected = OptionException.class ) + public void missingHelpOptionMeansRequiredOptionsMustBePresent() { + OptionParser parser = new OptionParser() { + { + accepts( "userid" ).withRequiredArg().required(); + accepts( "password" ).withRequiredArg().required(); + accepts( "help" ).forHelp(); + } + }; + + parser.parse( "" ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/RequiredUnlessExample.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/RequiredUnlessExample.java new file mode 100644 index 0000000000..f55f6ca91d --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/RequiredUnlessExample.java @@ -0,0 +1,14 @@ +package joptsimple.examples; + +import joptsimple.OptionParser; + +public class RequiredUnlessExample { + public static void main( String[] args ) { + OptionParser parser = new OptionParser(); + parser.accepts( "anonymous" ); + parser.accepts( "username" ).requiredUnless( "anonymous" ).withRequiredArg(); + parser.accepts( "password" ).requiredUnless( "anonymous" ).withRequiredArg(); + + parser.parse( "--anonymous" ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsClusteringTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsClusteringTest.java new file mode 100644 index 0000000000..9143e45d7d --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsClusteringTest.java @@ -0,0 +1,21 @@ +package joptsimple.examples; + +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class ShortOptionsClusteringTest { + @Test + public void allowsClusteringShortOptions() { + OptionParser parser = new OptionParser( "aBcd" ); + + OptionSet options = parser.parse( "-cdBa" ); + + assertTrue( options.has( "a" ) ); + assertTrue( options.has( "B" ) ); + assertTrue( options.has( "c" ) ); + assertTrue( options.has( "d" ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsClusteringWithArgumentTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsClusteringWithArgumentTest.java new file mode 100644 index 0000000000..695f6cebbc --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsClusteringWithArgumentTest.java @@ -0,0 +1,24 @@ +package joptsimple.examples; + +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class ShortOptionsClusteringWithArgumentTest { + @Test + public void allowsClusteringShortOptionsThatAcceptArguments() { + OptionParser parser = new OptionParser(); + parser.accepts( "a" ); + parser.accepts( "B" ); + parser.accepts( "c" ).withRequiredArg(); + + OptionSet options = parser.parse( "-aBcfoo" ); + + assertTrue( options.has( "a" ) ); + assertTrue( options.has( "B" ) ); + assertTrue( options.has( "c" ) ); + assertEquals( "foo", options.valueOf( "c" ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsTest.java new file mode 100644 index 0000000000..4e3487cd0e --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsTest.java @@ -0,0 +1,21 @@ +package joptsimple.examples; + +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class ShortOptionsTest { + @Test + public void supportsShortOptions() { + OptionParser parser = new OptionParser( "aB?*." ); + + OptionSet options = parser.parse( "-a", "-B", "-?" ); + + assertTrue( options.has( "a" ) ); + assertTrue( options.has( "B" ) ); + assertTrue( options.has( "?" ) ); + assertFalse( options.has( "." ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsWithArgumentPositioningTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsWithArgumentPositioningTest.java new file mode 100644 index 0000000000..720253ebf2 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsWithArgumentPositioningTest.java @@ -0,0 +1,28 @@ +package joptsimple.examples; + +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class ShortOptionsWithArgumentPositioningTest { + @Test + public void allowsDifferentFormsOfPairingArgumentWithOption() { + OptionParser parser = new OptionParser( "a:b:c::" ); + + OptionSet options = parser.parse( "-a", "foo", "-bbar", "-c=baz" ); + + assertTrue( options.has( "a" ) ); + assertTrue( options.hasArgument( "a" ) ); + assertEquals( "foo", options.valueOf( "a" ) ); + + assertTrue( options.has( "b" ) ); + assertTrue( options.hasArgument( "b" ) ); + assertEquals( "bar", options.valueOf( "b" ) ); + + assertTrue( options.has( "c" ) ); + assertTrue( options.hasArgument( "c" ) ); + assertEquals( "baz", options.valueOf( "c" ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsWithArgumentsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsWithArgumentsTest.java new file mode 100644 index 0000000000..3ee7911bd0 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsWithArgumentsTest.java @@ -0,0 +1,31 @@ +package joptsimple.examples; + +import static java.util.Arrays.*; +import static java.util.Collections.*; + +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class ShortOptionsWithArgumentsTest { + @Test + public void allowsOptionsToAcceptArguments() { + OptionParser parser = new OptionParser( "fc:q::" ); + + OptionSet options = parser.parse( "-f", "-c", "foo", "-q" ); + + assertTrue( options.has( "f" ) ); + + assertTrue( options.has( "c" ) ); + assertTrue( options.hasArgument( "c" ) ); + assertEquals( "foo", options.valueOf( "c" ) ); + assertEquals( asList( "foo" ), options.valuesOf( "c" ) ); + + assertTrue( options.has( "q" ) ); + assertFalse( options.hasArgument( "q" ) ); + assertNull( options.valueOf( "q" ) ); + assertEquals( emptyList(), options.valuesOf( "q" ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsWithMultipleArgumentsForSingleOptionTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsWithMultipleArgumentsForSingleOptionTest.java new file mode 100644 index 0000000000..8f113f859a --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ShortOptionsWithMultipleArgumentsForSingleOptionTest.java @@ -0,0 +1,31 @@ +package joptsimple.examples; + +import static java.util.Arrays.*; + +import joptsimple.OptionException; +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static org.junit.Assert.*; +import static org.junit.rules.ExpectedException.*; + +public class ShortOptionsWithMultipleArgumentsForSingleOptionTest { + @Rule public final ExpectedException thrown = none(); + + @Test + public void allowsMultipleValuesForAnOption() { + OptionParser parser = new OptionParser( "a:" ); + + OptionSet options = parser.parse( "-a", "foo", "-abar", "-a=baz" ); + + assertTrue( options.has( "a" ) ); + assertTrue( options.hasArgument( "a" ) ); + assertEquals( asList( "foo", "bar", "baz" ), options.valuesOf( "a" ) ); + + thrown.expect( OptionException.class ); + options.valueOf( "a" ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/SignallingEndOfOptionsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/SignallingEndOfOptionsTest.java new file mode 100644 index 0000000000..9fd1faefe7 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/SignallingEndOfOptionsTest.java @@ -0,0 +1,31 @@ +package joptsimple.examples; + +import static java.util.Arrays.*; + +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class SignallingEndOfOptionsTest { + @Test + public void doubleHyphenSignalsEndOfOptions() { + OptionParser parser = new OptionParser( "ab:c::de:f::" ); + + OptionSet options = parser.parse( "-a", "-b=foo", "-c=bar", "--", "-d", "-e", "baz", "-f", "biz" ); + + assertTrue( options.has( "a" ) ); + assertFalse( options.hasArgument( "a" ) ); + assertTrue( options.has( "b" ) ); + assertTrue( options.hasArgument( "b" ) ); + assertEquals( asList( "foo" ), options.valuesOf( "b" ) ); + assertTrue( options.has( "c" ) ); + assertTrue( options.hasArgument( "c" ) ); + assertEquals( asList( "bar" ), options.valuesOf( "c" ) ); + assertFalse( options.has( "d" ) ); + assertFalse( options.has( "e" ) ); + assertFalse( options.has( "f" ) ); + assertEquals( asList( "-d", "-e", "baz", "-f", "biz" ), options.nonOptionArguments() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/SpecialOptionalArgumentHandlingTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/SpecialOptionalArgumentHandlingTest.java new file mode 100644 index 0000000000..4f05559310 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/SpecialOptionalArgumentHandlingTest.java @@ -0,0 +1,31 @@ +package joptsimple.examples; + +import static java.util.Arrays.*; +import static java.util.Collections.*; + +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class SpecialOptionalArgumentHandlingTest { + @Test + public void handlesNegativeNumberOptionalArguments() { + OptionParser parser = new OptionParser(); + parser.accepts( "a" ).withOptionalArg().ofType( Integer.class ); + parser.accepts( "2" ); + + OptionSet options = parser.parse( "-a", "-2" ); + + assertTrue( options.has( "a" ) ); + assertFalse( options.has( "2" ) ); + assertEquals( asList( -2 ), options.valuesOf( "a" ) ); + + options = parser.parse( "-2", "-a" ); + + assertTrue( options.has( "a" ) ); + assertTrue( options.has( "2" ) ); + assertEquals( emptyList(), options.valuesOf( "a" ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/Strings.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/Strings.java new file mode 100644 index 0000000000..432350632e --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/Strings.java @@ -0,0 +1,19 @@ +package joptsimple.examples; + +import java.util.Iterator; + +import static java.util.Arrays.*; + +public class Strings { + public static String join( char delimiter, String... pieces ) { + StringBuilder builder = new StringBuilder(); + + for ( Iterator<String> iter = asList( pieces ).iterator(); iter.hasNext(); ) { + builder.append( iter.next() ); + if ( iter.hasNext() ) + builder.append( delimiter ); + } + + return builder.toString(); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/TypesafeOptionArgumentRetrievalTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/TypesafeOptionArgumentRetrievalTest.java new file mode 100644 index 0000000000..93cd0a5c5b --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/TypesafeOptionArgumentRetrievalTest.java @@ -0,0 +1,45 @@ +package joptsimple.examples; + +import java.io.File; + +import static java.util.Arrays.*; + +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import joptsimple.OptionSpec; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class TypesafeOptionArgumentRetrievalTest { + @Test + public void allowsTypesafeRetrievalOfOptionArguments() { + OptionParser parser = new OptionParser(); + OptionSpec<Integer> count = parser.accepts( "count" ).withRequiredArg().ofType( Integer.class ); + OptionSpec<File> outputDir = parser.accepts( "output-dir" ).withOptionalArg().ofType( File.class ); + OptionSpec<Void> verbose = parser.accepts( "verbose" ); + OptionSpec<File> files = parser.nonOptions().ofType( File.class ); + + OptionSet options = parser.parse( "--count", "3", "--output-dir", "/tmp", "--verbose", "a.txt", "b.txt" ); + + assertTrue( options.has( verbose ) ); + + assertTrue( options.has( count ) ); + assertTrue( options.hasArgument( count ) ); + Integer expectedCount = 3; + assertEquals( expectedCount, options.valueOf( count ) ); + assertEquals( expectedCount, count.value( options ) ); + assertEquals( asList( expectedCount ), options.valuesOf( count ) ); + assertEquals( asList( expectedCount ), count.values( options ) ); + assertEquals( asList( new File( "a.txt" ), new File( "b.txt" ) ), options.valuesOf( files ) ); + + assertTrue( options.has( outputDir ) ); + assertTrue( options.hasArgument( outputDir ) ); + File expectedFile = new File( "/tmp" ); + assertEquals( expectedFile, options.valueOf( outputDir ) ); + assertEquals( expectedFile, outputDir.value( options ) ); + assertEquals( asList( expectedFile ), options.valuesOf( outputDir ) ); + assertEquals( asList( expectedFile ), outputDir.values( options ) ); + assertEquals( asList( new File( "a.txt" ), new File( "b.txt" ) ), files.values( options ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/UnrecognizedOptionsAllowedTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/UnrecognizedOptionsAllowedTest.java new file mode 100644 index 0000000000..6dc9972028 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/UnrecognizedOptionsAllowedTest.java @@ -0,0 +1,23 @@ +package joptsimple.examples; + +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import org.junit.Test; + +import static java.util.Arrays.*; +import static org.junit.Assert.*; + +public class UnrecognizedOptionsAllowedTest { + @Test + public void acceptsLongOptions() { + OptionParser parser = new OptionParser(); + parser.allowsUnrecognizedOptions(); + parser.accepts( "f" ); + + OptionSet options = parser.parse( "-f", "-d" ); + + assertTrue( options.has( "f" ) ); + assertFalse( options.has( "d" ) ); + assertEquals( asList( "-d" ), options.nonOptionArguments() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ant/filters/HTMLEntitifier.java b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ant/filters/HTMLEntitifier.java new file mode 100644 index 0000000000..0eabe4ffa7 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/examples/ant/filters/HTMLEntitifier.java @@ -0,0 +1,80 @@ +package joptsimple.examples.ant.filters; + +import java.io.IOException; +import java.io.Reader; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tools.ant.filters.BaseFilterReader; +import org.apache.tools.ant.filters.ChainableReader; + +/** + * Ant filter class that transforms HTML special characters into their equivalent entities. + * + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class HTMLEntitifier extends BaseFilterReader implements ChainableReader { + private static final Map<Integer, String> ENTITIES = new HashMap<>(); + + static { + ENTITIES.put( (int) '<', "<" ); + ENTITIES.put( (int) '>', ">" ); + ENTITIES.put( (int) '"', """ ); + ENTITIES.put( (int) '&', "&" ); + } + + private String replacementData; + private int replacementIndex = -1; + + /** + * Creates "dummy" instances. + */ + public HTMLEntitifier() { + // empty on purpose + } + + /** + * @param source where the data to filter comes from + */ + public HTMLEntitifier( Reader source ) { + super( source ); + } + + /** + * {@inheritDoc} + */ + public Reader chain( Reader source ) { + HTMLEntitifier newFilter = new HTMLEntitifier( source ); + newFilter.setInitialized( true ); + + return newFilter; + } + + /** + * {@inheritDoc} + */ + @Override + public int read() throws IOException { + if ( !getInitialized() ) + setInitialized( true ); + + if ( replacementIndex > -1 ) { + int ch = replacementData.charAt( replacementIndex++ ); + + if ( replacementIndex >= replacementData.length() ) + replacementIndex = -1; + + return ch; + } + + int nextChar = in.read(); + + if ( ENTITIES.containsKey( nextChar ) ) { + replacementData = ENTITIES.get( nextChar ); + replacementIndex = 1; + return replacementData.charAt( 0 ); + } + + return nextChar; + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/internal/AbbreviationMapTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/AbbreviationMapTest.java new file mode 100644 index 0000000000..abd4302a0b --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/AbbreviationMapTest.java @@ -0,0 +1,361 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.internal; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class AbbreviationMapTest { + private AbbreviationMap<String> abbreviations; + + @Before + public void setUp() { + abbreviations = new AbbreviationMap<>(); + } + + @Test( expected = NullPointerException.class ) + public void nullValuesAreIllegal() { + abbreviations.put( "cannotAddNullValue", null ); + } + + @Test( expected = NullPointerException.class ) + public void nullKeysAreIllegalToAdd() { + abbreviations.put( null, "-1" ); + } + + @Test( expected = NullPointerException.class ) + public void nullKeysAreIllegalToCheckForContains() { + abbreviations.contains( null ); + } + + @Test( expected = IllegalArgumentException.class ) + public void zeroLengthKeysAreIllegalToAdd() { + abbreviations.put( "", "1" ); + } + + @Test( expected = NullPointerException.class ) + public void nullKeysAreIllegalToRemove() { + abbreviations.remove( null ); + } + + @Test( expected = IllegalArgumentException.class ) + public void zeroLengthKeysAreIllegalToRemove() { + abbreviations.remove( "" ); + } + + @Test + public void empty() { + assertFalse( abbreviations.contains( "boo" ) ); + assertNull( abbreviations.get( "boo" ) ); + } + + @Test + public void addingOne() { + abbreviations.put( "box", "2" ); + + assertTrue( abbreviations.contains( "box" ) ); + assertEquals( "2", abbreviations.get( "box" ) ); + assertTrue( abbreviations.contains( "bo" ) ); + assertEquals( "2", abbreviations.get( "bo" ) ); + assertTrue( abbreviations.contains( "b" ) ); + assertEquals( "2", abbreviations.get( "b" ) ); + } + + @Test + public void addingManyWithNoCommonPrefix() { + abbreviations.put( "box", "1" ); + abbreviations.put( "cat", "2" ); + abbreviations.put( "dog", "3" ); + + assertTrue( abbreviations.contains( "box" ) ); + assertEquals( "1", abbreviations.get( "box" ) ); + assertTrue( abbreviations.contains( "bo" ) ); + assertEquals( "1", abbreviations.get( "bo" ) ); + assertTrue( abbreviations.contains( "b" ) ); + assertEquals( "1", abbreviations.get( "b" ) ); + assertTrue( abbreviations.contains( "cat" ) ); + assertEquals( "2", abbreviations.get( "cat" ) ); + assertTrue( abbreviations.contains( "ca" ) ); + assertEquals( "2", abbreviations.get( "ca" ) ); + assertTrue( abbreviations.contains( "c" ) ); + assertEquals( "2", abbreviations.get( "c" ) ); + assertTrue( abbreviations.contains( "dog" ) ); + assertEquals( "3", abbreviations.get( "dog" ) ); + assertTrue( abbreviations.contains( "do" ) ); + assertEquals( "3", abbreviations.get( "do" ) ); + assertTrue( abbreviations.contains( "d" ) ); + assertEquals( "3", abbreviations.get( "d" ) ); + } + + @Test + public void addingTwoWithCommonPrefix() { + abbreviations.put( "box", "3" ); + abbreviations.put( "boy", "4" ); + + assertTrue( abbreviations.contains( "box" ) ); + assertEquals( "3", abbreviations.get( "box" ) ); + assertTrue( abbreviations.contains( "boy" ) ); + assertEquals( "4", abbreviations.get( "boy" ) ); + assertFalse( abbreviations.contains( "bo" ) ); + assertNull( abbreviations.get( "bo" ) ); + assertFalse( abbreviations.contains( "b" ) ); + assertNull( abbreviations.get( "b" ) ); + } + + @Test + public void addingThreeWithSuccessivelySmallerPrefixes() { + abbreviations.put( "boy", "3" ); + abbreviations.put( "bo", "2" ); + abbreviations.put( "b", "1" ); + + assertTrue( abbreviations.contains( "boy" ) ); + assertEquals( "3", abbreviations.get( "boy" ) ); + assertTrue( abbreviations.contains( "bo" ) ); + assertEquals( "2", abbreviations.get( "bo" ) ); + assertTrue( abbreviations.contains( "b" ) ); + assertEquals( "1", abbreviations.get( "b" ) ); + } + + @Test + public void addingThreeWithSuccessivelyLargerPrefixes() { + abbreviations.put( "b", "1" ); + abbreviations.put( "bo", "2" ); + abbreviations.put( "boy", "3" ); + + assertTrue( abbreviations.contains( "boy" ) ); + assertEquals( "3", abbreviations.get( "boy" ) ); + assertTrue( abbreviations.contains( "bo" ) ); + assertEquals( "2", abbreviations.get( "bo" ) ); + assertTrue( abbreviations.contains( "b" ) ); + assertEquals( "1", abbreviations.get( "b" ) ); + } + + @Test + public void addingThreeWithMixOfPrefixSize() { + abbreviations.put( "boy", "3" ); + abbreviations.put( "b", "1" ); + abbreviations.put( "bo", "2" ); + + assertTrue( abbreviations.contains( "boy" ) ); + assertEquals( "3", abbreviations.get( "boy" ) ); + assertTrue( abbreviations.contains( "bo" ) ); + assertEquals( "2", abbreviations.get( "bo" ) ); + assertTrue( abbreviations.contains( "b" ) ); + assertEquals( "1", abbreviations.get( "b" ) ); + } + + @Test + public void addingOneThenReplacing() { + abbreviations.put( "box", "2" ); + + assertTrue( abbreviations.contains( "box" ) ); + assertEquals( "2", abbreviations.get( "box" ) ); + assertTrue( abbreviations.contains( "bo" ) ); + assertEquals( "2", abbreviations.get( "bo" ) ); + assertTrue( abbreviations.contains( "b" ) ); + assertEquals( "2", abbreviations.get( "b" ) ); + + abbreviations.put( "box", "3" ); + + assertTrue( abbreviations.contains( "box" ) ); + assertEquals( "3", abbreviations.get( "box" ) ); + assertTrue( abbreviations.contains( "bo" ) ); + assertEquals( "3", abbreviations.get( "bo" ) ); + assertTrue( abbreviations.contains( "b" ) ); + assertEquals( "3", abbreviations.get( "b" ) ); + } + + @Test + public void removingNonExistentKeyHasNoEffect() { + abbreviations.put( "box", "2" ); + + abbreviations.remove( "cat" ); + + assertTrue( abbreviations.contains( "box" ) ); + assertEquals( "2", abbreviations.get( "box" ) ); + assertTrue( abbreviations.contains( "bo" ) ); + assertEquals( "2", abbreviations.get( "bo" ) ); + assertTrue( abbreviations.contains( "b" ) ); + assertEquals( "2", abbreviations.get( "b" ) ); + } + + @Test + public void removingSingleKey() { + abbreviations.put( "box", "3" ); + + abbreviations.remove( "box" ); + + assertFalse( abbreviations.contains( "box" ) ); + assertNull( abbreviations.get( "box" ) ); + assertFalse( abbreviations.contains( "bo" ) ); + assertNull( abbreviations.get( "bo" ) ); + assertFalse( abbreviations.contains( "b" ) ); + assertNull( abbreviations.get( "b" ) ); + } + + @Test + public void cannotRemoveByUniqueAbbreviation() { + abbreviations.put( "box", "4" ); + + abbreviations.remove( "bo" ); + abbreviations.remove( "b" ); + + assertTrue( abbreviations.contains( "box" ) ); + assertEquals( "4", abbreviations.get( "box" ) ); + assertTrue( abbreviations.contains( "bo" ) ); + assertEquals( "4", abbreviations.get( "bo" ) ); + assertTrue( abbreviations.contains( "b" ) ); + assertEquals( "4", abbreviations.get( "b" ) ); + } + + @Test + public void removeKeyWithCommonPrefix() { + abbreviations.put( "box", "-1" ); + abbreviations.put( "boy", "-2" ); + + abbreviations.remove( "box" ); + + assertFalse( abbreviations.contains( "box" ) ); + assertNull( abbreviations.get( "box" ) ); + assertTrue( abbreviations.contains( "boy" ) ); + assertEquals( "-2", abbreviations.get( "boy" ) ); + assertTrue( abbreviations.contains( "bo" ) ); + assertEquals( "-2", abbreviations.get( "bo" ) ); + assertTrue( abbreviations.contains( "b" ) ); + assertEquals( "-2", abbreviations.get( "b" ) ); + } + + @Test + public void addKeysWithCommonPrefixThenRemoveNonExistentKeyWithCommonPrefix() { + abbreviations.put( "box", "-1" ); + abbreviations.put( "boy", "-2" ); + + abbreviations.remove( "bop" ); + + assertTrue( abbreviations.contains( "box" ) ); + assertEquals( "-1", abbreviations.get( "box" ) ); + assertTrue( abbreviations.contains( "boy" ) ); + assertEquals( "-2", abbreviations.get( "boy" ) ); + assertFalse( abbreviations.contains( "bo" ) ); + assertNull( abbreviations.get( "bo" ) ); + assertFalse( abbreviations.contains( "b" ) ); + assertNull( abbreviations.get( "b" ) ); + } + + @Test + public void addKeysWithCommonPrefixesStairstepStyle() { + abbreviations.put( "a", "1" ); + abbreviations.put( "abc", "2" ); + + assertTrue( abbreviations.contains( "a" ) ); + assertEquals( "1", abbreviations.get( "a" ) ); + assertTrue( abbreviations.contains( "ab" ) ); + assertEquals( "2", abbreviations.get( "ab" ) ); + assertTrue( abbreviations.contains( "abc" ) ); + assertEquals( "2", abbreviations.get( "abc" ) ); + + abbreviations.put( "abcde", "3" ); + + assertTrue( abbreviations.contains( "a" ) ); + assertEquals( "1", abbreviations.get( "a" ) ); + assertFalse( abbreviations.contains( "ab" ) ); + assertNull( abbreviations.get( "ab" ) ); + assertTrue( abbreviations.contains( "abc" ) ); + assertEquals( "2", abbreviations.get( "abc" ) ); + assertTrue( abbreviations.contains( "abcd" ) ); + assertEquals( "3", abbreviations.get( "abcd" ) ); + assertTrue( abbreviations.contains( "abcde" ) ); + assertEquals( "3", abbreviations.get( "abcde" ) ); + } + + @Test + public void addKeysWithCommonPrefixesStairstepStyleJumbled() { + abbreviations.put( "a", "1" ); + abbreviations.put( "abcde", "3" ); + abbreviations.put( "abc", "2" ); + + assertTrue( abbreviations.contains( "a" ) ); + assertEquals( "1", abbreviations.get( "a" ) ); + assertFalse( abbreviations.contains( "ab" ) ); + assertNull( abbreviations.get( "ab" ) ); + assertTrue( abbreviations.contains( "abc" ) ); + assertEquals( "2", abbreviations.get( "abc" ) ); + assertTrue( abbreviations.contains( "abcd" ) ); + assertEquals( "3", abbreviations.get( "abcd" ) ); + assertTrue( abbreviations.contains( "abcde" ) ); + assertEquals( "3", abbreviations.get( "abcde" ) ); + } + + @Test + public void multipleKeysWithCommonPrefix() { + abbreviations.put( "good", "4" ); + abbreviations.put( "goodyear", "8" ); + abbreviations.put( "go", "2" ); + abbreviations.put( "goodyea", "7" ); + abbreviations.put( "goodye", "6" ); + + assertFalse( abbreviations.contains( "g" ) ); + assertNull( abbreviations.get( "g" ) ); + assertTrue( abbreviations.contains( "go" ) ); + assertEquals( "2", abbreviations.get( "go" ) ); + assertFalse( abbreviations.contains( "goo" ) ); + assertNull( abbreviations.get( "goo" ) ); + assertTrue( abbreviations.contains( "good" ) ); + assertEquals( "4", abbreviations.get( "good" ) ); + assertFalse( abbreviations.contains( "goody" ) ); + assertNull( abbreviations.get( "goody" ) ); + assertTrue( abbreviations.contains( "goodye" ) ); + assertEquals( "6", abbreviations.get( "goodye" ) ); + assertTrue( abbreviations.contains( "goodyea" ) ); + assertEquals( "7", abbreviations.get( "goodyea" ) ); + assertTrue( abbreviations.contains( "goodyea" ) ); + assertEquals( "8", abbreviations.get( "goodyear" ) ); + + abbreviations.remove( "goodyea" ); + + assertFalse( abbreviations.contains( "g" ) ); + assertNull( abbreviations.get( "g" ) ); + assertTrue( abbreviations.contains( "go" ) ); + assertEquals( "2", abbreviations.get( "go" ) ); + assertFalse( abbreviations.contains( "goo" ) ); + assertNull( abbreviations.get( "goo" ) ); + assertTrue( abbreviations.contains( "good" ) ); + assertEquals( "4", abbreviations.get( "good" ) ); + assertFalse( abbreviations.contains( "goody" ) ); + assertNull( abbreviations.get( "goody" ) ); + assertTrue( abbreviations.contains( "goodye" ) ); + assertEquals( "6", abbreviations.get( "goodye" ) ); + assertTrue( abbreviations.contains( "goodyea" ) ); + assertEquals( "8", abbreviations.get( "goodyea" ) ); + assertTrue( abbreviations.contains( "goodyea" ) ); + assertEquals( "8", abbreviations.get( "goodyear" ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/internal/AbbreviationMapToJavaUtilMapTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/AbbreviationMapToJavaUtilMapTest.java new file mode 100644 index 0000000000..8bc062135b --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/AbbreviationMapToJavaUtilMapTest.java @@ -0,0 +1,148 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.internal; + +import static java.util.Collections.*; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class AbbreviationMapToJavaUtilMapTest { + private AbbreviationMap<String> abbreviations; + + @Before + public void setUp() { + abbreviations = new AbbreviationMap<>(); + } + + @Test + public void empty() { + assertEquals( emptyMap(), abbreviations.toJavaUtilMap() ); + } + + @Test + public void addingOne() { + abbreviations.put( "box", "2" ); + + assertEquals( singletonMap( "box", "2" ), abbreviations.toJavaUtilMap() ); + } + + @Test + public void addingManyWithNoCommonPrefix() { + abbreviations.put( "box", "1" ); + abbreviations.put( "cat", "2" ); + abbreviations.put( "dog", "3" ); + + assertEquals( "{box=1, cat=2, dog=3}", abbreviations.toJavaUtilMap().toString() ); + } + + @Test + public void addingTwoWithCommonPrefix() { + abbreviations.put( "box", "3" ); + abbreviations.put( "boy", "4" ); + + assertEquals( "{box=3, boy=4}", abbreviations.toJavaUtilMap().toString() ); + } + + @Test + public void addingThreeWithSuccessivelySmallerPrefixes() { + abbreviations.put( "boy", "3" ); + abbreviations.put( "bo", "2" ); + abbreviations.put( "b", "1" ); + + assertEquals( "{b=1, bo=2, boy=3}", abbreviations.toJavaUtilMap().toString() ); + } + + @Test + public void addingThreeWithSuccessivelyLargerPrefixes() { + abbreviations.put( "b", "1" ); + abbreviations.put( "bo", "2" ); + abbreviations.put( "boy", "3" ); + + assertEquals( "{b=1, bo=2, boy=3}", abbreviations.toJavaUtilMap().toString() ); + } + + @Test + public void addingThreeWithMixOfPrefixSize() { + abbreviations.put( "boy", "3" ); + abbreviations.put( "b", "1" ); + abbreviations.put( "bo", "2" ); + + assertEquals( "{b=1, bo=2, boy=3}", abbreviations.toJavaUtilMap().toString() ); + } + + @Test + public void addingOneThenReplacing() { + abbreviations.put( "box", "2" ); + abbreviations.put( "box", "3" ); + + assertEquals( "{box=3}", abbreviations.toJavaUtilMap().toString() ); + } + + @Test + public void removeKeyWithCommonPrefix() { + abbreviations.put( "box", "-1" ); + abbreviations.put( "boy", "-2" ); + abbreviations.remove( "box" ); + + assertEquals( "{boy=-2}", abbreviations.toJavaUtilMap().toString() ); + } + + @Test + public void addKeysWithCommonPrefixesStairstepStyle() { + abbreviations.put( "a", "1" ); + abbreviations.put( "abc", "2" ); + abbreviations.put( "abcde", "3" ); + + assertEquals( "{a=1, abc=2, abcde=3}", abbreviations.toJavaUtilMap().toString() ); + } + + @Test + public void addKeysWithCommonPrefixesStairstepStyleJumbled() { + abbreviations.put( "a", "1" ); + abbreviations.put( "abcde", "3" ); + abbreviations.put( "abc", "2" ); + + assertEquals( "{a=1, abc=2, abcde=3}", abbreviations.toJavaUtilMap().toString() ); + } + + @Test + public void multipleKeysWithCommonPrefix() { + abbreviations.put( "good", "4" ); + abbreviations.put( "goodyear", "8" ); + abbreviations.put( "go", "2" ); + abbreviations.put( "goodyea", "7" ); + abbreviations.put( "goodye", "6" ); + abbreviations.remove( "goodyea" ); + + assertEquals( "{go=2, good=4, goodye=6, goodyear=8}", abbreviations.toJavaUtilMap().toString() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/internal/ClassesUtilityClassTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/ClassesUtilityClassTest.java new file mode 100644 index 0000000000..89f3ea2430 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/ClassesUtilityClassTest.java @@ -0,0 +1,37 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.internal; + +import joptsimple.UtilityClassesUninstantiabilityHarness; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class ClassesUtilityClassTest extends UtilityClassesUninstantiabilityHarness { + public ClassesUtilityClassTest() { + super( Classes.class ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/internal/MessagesUtilityClassTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/MessagesUtilityClassTest.java new file mode 100644 index 0000000000..a0c1051ed8 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/MessagesUtilityClassTest.java @@ -0,0 +1,37 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.internal; + +import joptsimple.UtilityClassesUninstantiabilityHarness; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class MessagesUtilityClassTest extends UtilityClassesUninstantiabilityHarness { + public MessagesUtilityClassTest() { + super( Messages.class ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/internal/Problematic.java b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/Problematic.java new file mode 100644 index 0000000000..9ec93d62a7 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/Problematic.java @@ -0,0 +1,51 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.internal; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +class Problematic { + private Problematic() { + // no-op + } + + Problematic( String s ) { + throw new IllegalStateException(s); + } + + private static void boo() { + // no-op + } + + static void mute() { + new Problematic().stuff(); + } + + void stuff() { + boo(); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/internal/ReflectionTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/ReflectionTest.java new file mode 100644 index 0000000000..06f96829c4 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/ReflectionTest.java @@ -0,0 +1,109 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.internal; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static joptsimple.internal.Reflection.*; +import static org.junit.rules.ExpectedException.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class ReflectionTest { + @Rule public final ExpectedException thrown = none(); + + @Test + public void invokingConstructorQuietlyWrapsInstantiationException() throws Exception { + Constructor<AbstractProblematic> constructor = AbstractProblematic.class.getDeclaredConstructor(); + + thrown.expect( ReflectionException.class ); + thrown.expectMessage( InstantiationException.class.getName() ); + + instantiate( constructor ); + } + + @Test + public void invokingConstructorQuietlyWrapsIllegalAccessException() throws Exception { + Constructor<Problematic> constructor = Problematic.class.getDeclaredConstructor(); + + thrown.expect( ReflectionException.class ); + thrown.expectMessage( IllegalAccessException.class.getName() ); + + instantiate( constructor ); + } + + @Test + public void invokingConstructorQuietlyWrapsCauseOfInvocationTargetException() throws Exception { + Constructor<Problematic> constructor = Problematic.class.getDeclaredConstructor( String.class ); + + thrown.expect( ReflectionException.class ); + thrown.expectMessage( IllegalStateException.class.getName() ); + + instantiate( constructor, "arg" ); + } + + @Test + public void invokingConstructorQuietlyWrapsIllegalArgumentException() throws Exception { + Constructor<Problematic> constructor = Problematic.class.getDeclaredConstructor(String.class); + + thrown.expect( ReflectionException.class ); + thrown.expectMessage( IllegalArgumentException.class.getName() ); + + instantiate( constructor ); + } + + @Test + public void invokingStaticMethodQuietlyWrapsIllegalAccessException() throws Exception { + Method method = Problematic.class.getDeclaredMethod( "boo" ); + + thrown.expect( ReflectionException.class ); + thrown.expectMessage( IllegalAccessException.class.getName() ); + + invoke( method ); + } + + @Test + public void invokingStaticMethodQuietlyWrapsIllegalArgumentException() throws Exception { + Method method = Problematic.class.getDeclaredMethod( "mute" ); + + thrown.expect( ReflectionException.class ); + thrown.expectMessage( IllegalArgumentException.class.getName() ); + + invoke( method, new Object() ); + } + + private abstract static class AbstractProblematic { + protected AbstractProblematic() { + // no-op + } + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/internal/ReflectionUtilityClassTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/ReflectionUtilityClassTest.java new file mode 100644 index 0000000000..7634a4900f --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/ReflectionUtilityClassTest.java @@ -0,0 +1,37 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.internal; + +import joptsimple.UtilityClassesUninstantiabilityHarness; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class ReflectionUtilityClassTest extends UtilityClassesUninstantiabilityHarness { + public ReflectionUtilityClassTest() { + super( Reflection.class ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/internal/RowEqualsHashCodeTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/RowEqualsHashCodeTest.java new file mode 100644 index 0000000000..e1ad850945 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/RowEqualsHashCodeTest.java @@ -0,0 +1,49 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.internal; + +import org.infinitest.toolkit.StrictEqualsHashCodeTestSupport; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class RowEqualsHashCodeTest extends StrictEqualsHashCodeTestSupport { + @Override + protected Object equalButDifferentClass() { + return new Row( "o", "d" ) { + }; + } + + @Override + protected Object equal() throws Exception { + return new Row( "o", "d" ); + } + + @Override + protected Object notEqual() throws Exception { + return new Row( "o", "e" ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/internal/RowsTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/RowsTest.java new file mode 100644 index 0000000000..c07522de15 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/RowsTest.java @@ -0,0 +1,83 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.internal; + +import org.junit.Test; + +import static joptsimple.internal.Strings.*; +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class RowsTest { + @Test + public void optionsAndDescriptionsWithinOverallWidth() { + Rows rows = new Rows( 40, 2 ); + rows.add( "left one", "right one" ); + rows.add( "another left one", "another right one" ); + + assertRows( rows, + "left one right one ", + "another left one another right one" ); + } + + @Test + public void someOptionsExceedOverallWidth() { + Rows rows = new Rows( 40, 2 ); + rows.add( "left one is pretty freaking long to be over here", "right one" ); + rows.add( "another left one also has length that is quite excessive", "another right one" ); + + assertRows( rows, + "left one is pretty right one ", + " freaking long to ", + " be over here ", + "another left one another right one", + " also has length ", + " that is quite ", + " excessive " ); + } + + @Test + public void someDescriptionsExceedOverallWidth() { + Rows rows = new Rows( 40, 2 ); + rows.add( "left one", "right one for the time we have chosen" ); + rows.add( "another left one", "another right one could be used here instead" ); + + assertRows( rows, + "left one right one for the ", + " time we have chosen", + "another left one another right one ", + " could be used here ", + " instead " ); + } + + private void assertRows( Rows rows, String... expected ) { + rows.fitToWidth(); + + assertEquals( join( expected, LINE_SEPARATOR ) + LINE_SEPARATOR, rows.render() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/internal/SimpleOptionNameMapTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/SimpleOptionNameMapTest.java new file mode 100644 index 0000000000..ae9ae0d4fd --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/SimpleOptionNameMapTest.java @@ -0,0 +1,93 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.internal; + +import java.util.List; +import java.util.Map; + +import org.junit.Test; + +import static java.util.Arrays.*; + +import static org.junit.Assert.*; + +public class SimpleOptionNameMapTest { + private static final Integer VALUE = 1; + private static final String KEY = "someKey"; + private static final String KEY2 = "someOtherKey"; + + @Test + public void putAndContains() { + SimpleOptionNameMap<Integer> map = new SimpleOptionNameMap<>(); + assertFalse( map.contains( KEY ) ); + + map.put( KEY, 1 ); + + assertTrue( map.contains( KEY ) ); + } + + @Test + public void get() { + SimpleOptionNameMap<Integer> map = new SimpleOptionNameMap<>(); + assertNull( map.get( KEY ) ); + + map.put( KEY, VALUE ); + + assertEquals( VALUE, map.get( KEY ) ); + } + + @Test + public void putAll() { + SimpleOptionNameMap<Integer> map = new SimpleOptionNameMap<>(); + List<String> keys = asList( KEY, KEY2 ); + + map.putAll( keys, VALUE ); + + assertEquals( VALUE, map.get( KEY ) ); + assertEquals( VALUE, map.get( KEY2 ) ); + } + + @Test + public void remove() { + SimpleOptionNameMap<Integer> map = new SimpleOptionNameMap<>(); + map.put( KEY, 1 ); + + map.remove( KEY ); + + assertFalse( map.contains( KEY ) ); + } + + @Test + public void toJavaUtilMap() { + SimpleOptionNameMap<Integer> map = new SimpleOptionNameMap<>(); + map.put( KEY, VALUE ); + + Map<String, Integer> javaUtilMap = map.toJavaUtilMap(); + + assertEquals( VALUE, javaUtilMap.get( KEY ) ); + assertEquals( 1, javaUtilMap.size() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/internal/StringsUtilityClassTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/StringsUtilityClassTest.java new file mode 100644 index 0000000000..a56b2a53c5 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/internal/StringsUtilityClassTest.java @@ -0,0 +1,37 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.internal; + +import joptsimple.UtilityClassesUninstantiabilityHarness; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class StringsUtilityClassTest extends UtilityClassesUninstantiabilityHarness { + public StringsUtilityClassTest() { + super( Strings.class ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/util/DateConverterTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/util/DateConverterTest.java new file mode 100644 index 0000000000..93baa0bacc --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/util/DateConverterTest.java @@ -0,0 +1,152 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.util; + +import java.text.DateFormat; +import java.text.FieldPosition; +import java.text.NumberFormat; +import java.text.ParsePosition; +import java.text.SimpleDateFormat; +import java.util.Date; + +import static java.text.DateFormat.*; + +import joptsimple.ValueConversionException; +import joptsimple.ValueConverter; +import org.joda.time.LocalDate; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static joptsimple.util.DateConverter.*; +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; +import static org.junit.rules.ExpectedException.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class DateConverterTest { + @Rule public final ExpectedException thrown = none(); + + private DateFormat notASimpleDateFormat; + private SimpleDateFormat monthDayYear; + + @Before + public void setUp() { + notASimpleDateFormat = new DateFormat() { + private static final long serialVersionUID = -1L; + + { + setNumberFormat( NumberFormat.getInstance() ); + } + + @Override + public StringBuffer format( Date date, StringBuffer toAppendTo, FieldPosition fieldPosition ) { + return null; + } + + @Override + public Date parse( String source, ParsePosition pos ) { + return null; + } + }; + + monthDayYear = new SimpleDateFormat( "MM/dd/yyyy" ); + } + + @Test( expected = NullPointerException.class ) + public void rejectsNullDateFormatter() { + new DateConverter( null ); + } + + @Test + public void shouldConvertValuesToDatesUsingADateFormat() { + ValueConverter<Date> converter = new DateConverter( monthDayYear ); + + assertEquals( new LocalDate( 2009, 1, 24 ).toDate(), converter.convert( "01/24/2009" ) ); + } + + @Test + public void rejectsNonParsableValues() { + thrown.expect( ValueConversionException.class ); + + new DateConverter( getDateInstance() ).convert( "@(#*^" ); + } + + @Test + public void rejectsValuesThatDoNotEntirelyMatch() { + thrown.expect( ValueConversionException.class ); + + new DateConverter( monthDayYear ).convert( "12/25/09 00:00:00" ); + } + + @Test + public void shouldCreateSimpleDateFormatConverter() { + assertEquals( new LocalDate( 2009, 7, 4 ).toDate(), datePattern( "MM/dd/yyyy" ).convert( "07/04/2009" ) ); + } + + @Test + public void rejectsNullDatePattern() { + thrown.expect( NullPointerException.class ); + + datePattern( null ); + } + + @Test + public void shouldRaiseExceptionThatContainsDatePatternAndValue() { + thrown.expect( ValueConversionException.class ); + thrown.expectMessage( "qwe" ); + thrown.expectMessage( monthDayYear.toPattern() ); + + new DateConverter( monthDayYear ).convert( "qwe" ); + } + + @Test + public void shouldRaiseExceptionThatContainsValueOnlyIfNotASimpleDateFormat() { + thrown.expect( ValueConversionException.class ); + thrown.expectMessage( "asdf" ); + thrown.expectMessage( not( containsString( notASimpleDateFormat.toString() ) ) ); + + new DateConverter( notASimpleDateFormat ).convert( "asdf" ); + } + + @Test + public void shouldAnswerCorrectValueType() { + assertSame( Date.class, new DateConverter( monthDayYear ).valueType() ); + } + + @Test + public void shouldGiveNoValuePatternIfFormatterNotASimpleDateFormat() { + assertEquals( "", new DateConverter( notASimpleDateFormat ).valuePattern() ); + } + + @Test + public void shouldGiveValuePatternIfFormatterIsASimpleDateFormat() { + assertEquals( monthDayYear.toPattern(), datePattern( monthDayYear.toPattern() ).valuePattern() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/util/EnumConverterTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/util/EnumConverterTest.java new file mode 100644 index 0000000000..617f1462c1 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/util/EnumConverterTest.java @@ -0,0 +1,95 @@ +/* + The MIT License + + Copyright (c) 2004-2014 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.util; + +import joptsimple.ValueConversionException; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; +import static org.junit.rules.ExpectedException.none; + +/** + * @author <a href="mailto:christian.ohr@gmail.com">Christian Ohr</a> + */ +public class EnumConverterTest { + @Rule + public final ExpectedException thrown = none(); + + private EnumConverter<TestEnum> converter; + + @Before + public void setUp() { + converter = new TestEnumConverter(); + } + + @Test + public void convertsEnumValuesToEnum() { + assertEquals( TestEnum.A, converter.convert( "A" ) ); + } + + @Test + public void rejectsNonEnumeratedValues() { + thrown.expect( ValueConversionException.class ); + + converter.convert( "Z" ); + } + + @Test + public void answersCorrectValueType() { + assertSame( TestEnum.class, converter.valueType() ); + } + + @Test + public void givesDefaultValuePattern() { + assertEquals( "[A,B,C,D]", converter.valuePattern() ); + } + + @Test + public void givesCustomValuePattern() { + converter.setDelimiters( "(|)" ); + + assertEquals( "(A|B|C|D)", converter.valuePattern() ); + } + + @Test + public void ignoresCase() { + assertEquals( TestEnum.A, converter.convert( "a" ) ); + } + + private static class TestEnumConverter extends EnumConverter<TestEnum> { + TestEnumConverter() { + super( TestEnum.class ); + } + } + + private static enum TestEnum { + A, B, C, D + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/util/InetAddressConverterTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/util/InetAddressConverterTest.java new file mode 100644 index 0000000000..98f418ff3a --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/util/InetAddressConverterTest.java @@ -0,0 +1,60 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.util; + +import java.net.InetAddress; +import java.util.Random; + +import joptsimple.ValueConversionException; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; +import static org.junit.Assume.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class InetAddressConverterTest { + private InetAddressConverter converter; + + @Before + public void setUp() { + converter = new InetAddressConverter(); + } + + @Test + public void localhost() throws Exception { + assumeTrue( InetAddress.getByName( "127.0.0.1" ).isReachable( 5000 ) ); + + assertEquals( "127.0.0.1", converter.convert( "localhost" ).getHostAddress() ); + } + + @Test( expected = ValueConversionException.class ) + public void unknownHost() { + converter.convert( "!(@&#()!*@&#" ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/util/KeyValuePairTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/util/KeyValuePairTest.java new file mode 100644 index 0000000000..e0c64e9efd --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/util/KeyValuePairTest.java @@ -0,0 +1,88 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.util; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class KeyValuePairTest { + @Test( expected = NullPointerException.class ) + public void nullArg() { + KeyValuePair.valueOf( null ); + } + + @Test + public void empty() { + KeyValuePair pair = KeyValuePair.valueOf( "" ); + + assertEquals( "", pair.key ); + assertEquals( "", pair.value ); + } + + @Test + public void noEqualsSign() { + KeyValuePair pair = KeyValuePair.valueOf( "aString" ); + + assertEquals( "aString", pair.key ); + assertEquals( "", pair.value ); + } + + @Test + public void signAtEnd() { + KeyValuePair pair = KeyValuePair.valueOf( "aKey=" ); + + assertEquals( "aKey", pair.key ); + assertEquals( "", pair.value ); + } + + @Test + public void signAtStart() { + KeyValuePair pair = KeyValuePair.valueOf( "=aValue" ); + + assertEquals( "", pair.key ); + assertEquals( "aValue", pair.value ); + } + + @Test + public void typical() { + KeyValuePair pair = KeyValuePair.valueOf( "aKey=aValue" ); + + assertEquals( "aKey", pair.key ); + assertEquals( "aValue", pair.value ); + } + + @Test + public void multipleEqualsSignsDoNotMatter() { + KeyValuePair pair = KeyValuePair.valueOf( "aKey=1=2=3=4" ); + + assertEquals( "aKey", pair.key ); + assertEquals( "1=2=3=4", pair.value ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/util/KeyValuePairUnequalKeysTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/util/KeyValuePairUnequalKeysTest.java new file mode 100644 index 0000000000..fc130bf938 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/util/KeyValuePairUnequalKeysTest.java @@ -0,0 +1,43 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.util; + +import org.infinitest.toolkit.EqualsHashCodeTestSupport; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class KeyValuePairUnequalKeysTest extends EqualsHashCodeTestSupport { + @Override + protected KeyValuePair equal() { + return KeyValuePair.valueOf( "x=z" ); + } + + @Override + protected KeyValuePair notEqual() { + return KeyValuePair.valueOf( "y=z" ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/util/KeyValuePairUnequalValuesTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/util/KeyValuePairUnequalValuesTest.java new file mode 100644 index 0000000000..4bb36b71c5 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/util/KeyValuePairUnequalValuesTest.java @@ -0,0 +1,43 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.util; + +import org.infinitest.toolkit.EqualsHashCodeTestSupport; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class KeyValuePairUnequalValuesTest extends EqualsHashCodeTestSupport { + @Override + protected KeyValuePair equal() { + return KeyValuePair.valueOf( "x=y" ); + } + + @Override + protected KeyValuePair notEqual() { + return KeyValuePair.valueOf( "x=z" ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/util/PathConverterTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/util/PathConverterTest.java new file mode 100644 index 0000000000..6b543936cd --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/util/PathConverterTest.java @@ -0,0 +1,104 @@ +package joptsimple.util; + +import java.nio.file.Files; +import java.nio.file.Path; + +import joptsimple.ValueConversionException; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static joptsimple.util.PathProperties.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class PathConverterTest { + @Rule + public ExpectedException exception = ExpectedException.none(); + + @Test + public void convertsValuesToPaths() throws Exception { + Path path = Files.createTempFile( "prefix", null ); + path.toFile().deleteOnExit(); + + String pathName = path.toString(); + + assertEquals( path, new PathConverter( null ).convert( pathName ) ); + assertEquals( path, new PathConverter().convert( pathName ) ); + } + + @Test + public void answersCorrectValueType() { + assertEquals( Path.class, new PathConverter().valueType() ); + } + + @Test + public void testReadableAndOverwritableFile() throws Exception { + Path path = Files.createTempFile( "prefix", null ); + path.toFile().deleteOnExit(); + + String pathName = path.toString(); + + assertTrue( Files.isReadable( new PathConverter( READABLE ).convert( pathName ) ) ); + assertTrue( Files.exists( new PathConverter( READABLE ).convert( pathName ) ) ); + assertTrue( Files.isWritable( new PathConverter( READABLE ).convert( pathName ) ) ); + assertTrue( Files.isWritable( new PathConverter( FILE_OVERWRITABLE).convert( pathName ) ) ); + } + + @Test + public void testNotExisting() throws Exception { + Path path = Files.createTempFile( "prefix", null ); + + Files.deleteIfExists( path ); + + assertFalse( Files.exists( new PathConverter( NOT_EXISTING ).convert( path.toString() ) ) ); + } + + @Test + public void testNotReadable() throws Exception { + Path path = Files.createTempFile( "prefix", null ); + String pathName = path.toString(); + Files.deleteIfExists( path ); + + exception.expect( ValueConversionException.class ); + exception.expectMessage( "File [" + pathName ); + + new PathConverter( READABLE ).convert( pathName ); + } + + @Test + public void testDirectoryExisting() throws Exception { + Path path = Files.createTempDirectory( "prefix" ); + path.toFile().deleteOnExit(); + + String pathName = path.toString(); + + assertTrue( Files.isDirectory( new PathConverter( DIRECTORY_EXISTING ).convert( pathName ) ) ); + } + + @Test + public void testDirectoryNotOverwritable() throws Exception { + Path path = Files.createTempDirectory( "prefix" ); + path.toFile().deleteOnExit(); + + String pathName = path.toString(); + + exception.expect( ValueConversionException.class ); + exception.expectMessage( "File [" + pathName ); + + new PathConverter( FILE_OVERWRITABLE).convert( pathName ); + } + + @Test + public void testNotExistingNotOverwritable() throws Exception { + Path path = Files.createTempDirectory( "prefix" ); + String pathName = path.toString(); + Files.deleteIfExists( path ); + + exception.expect( ValueConversionException.class ); + exception.expectMessage( "File [" + pathName ); + + new PathConverter( FILE_OVERWRITABLE ).convert( pathName ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/util/PathPropertiesTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/util/PathPropertiesTest.java new file mode 100644 index 0000000000..1c6bf59718 --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/util/PathPropertiesTest.java @@ -0,0 +1,54 @@ +package joptsimple.util; + +import java.nio.file.Files; +import java.nio.file.Path; + +import org.junit.Test; + +import static org.junit.Assert.*; + +import static joptsimple.util.PathProperties.*; + +public class PathPropertiesTest { + @Test + public void readableFile() throws Exception { + Path path = Files.createTempFile("prefix", null); + + path.toFile().deleteOnExit(); + + assertTrue( READABLE.accept( path ) ); + assertFalse( DIRECTORY_EXISTING.accept( path ) ); + assertTrue( FILE_EXISTING.accept( path ) ); + assertTrue( FILE_OVERWRITABLE.accept( path ) ); + assertTrue( WRITABLE.accept( path ) ); + assertFalse( NOT_EXISTING.accept( path ) ); + } + + @Test + public void nonExisting() throws Exception { + Path path = Files.createTempFile( "prefix", null ); + + Files.deleteIfExists( path ); + + assertFalse( READABLE.accept( path ) ); + assertFalse( DIRECTORY_EXISTING.accept( path ) ); + assertFalse( FILE_EXISTING.accept( path ) ); + assertFalse( FILE_OVERWRITABLE.accept( path ) ); + assertTrue( NOT_EXISTING.accept( path ) ); + assertFalse( WRITABLE.accept( path ) ); + } + + @Test + public void directory() throws Exception { + Path path = Files.createTempDirectory( "prefix" ); + + path.toFile().deleteOnExit(); + + assertTrue( READABLE.accept( path ) ); + assertTrue( DIRECTORY_EXISTING.accept( path ) ); + assertFalse( FILE_EXISTING.accept( path ) ); + assertFalse( FILE_OVERWRITABLE.accept( path ) ); + assertFalse( NOT_EXISTING.accept( path ) ); + assertTrue( WRITABLE.accept( path ) ); + } +} diff --git a/third_party/java/jopt-simple/src/test/java/joptsimple/util/RegexMatcherTest.java b/third_party/java/jopt-simple/src/test/java/joptsimple/util/RegexMatcherTest.java new file mode 100644 index 0000000000..56eae7ec5a --- /dev/null +++ b/third_party/java/jopt-simple/src/test/java/joptsimple/util/RegexMatcherTest.java @@ -0,0 +1,84 @@ +/* + The MIT License + + Copyright (c) 2004-2015 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +package joptsimple.util; + +import joptsimple.ValueConversionException; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static joptsimple.util.RegexMatcher.*; +import static org.junit.Assert.*; +import static org.junit.rules.ExpectedException.*; + +/** + * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a> + */ +public class RegexMatcherTest { + @Rule public final ExpectedException thrown = none(); + + private RegexMatcher abc; + + @Before + public void setUp() { + abc = new RegexMatcher( "abc", 0 ); + } + + @Test + public void shouldAttemptToMatchValueAgainstARegex() { + assertEquals( "abc", abc.convert( "abc" ) ); + } + + @Test( expected = ValueConversionException.class ) + public void rejectsValueThatDoesNotMatchRegex() { + abc.convert( "abcd" ); + } + + @Test + public void raisesExceptionContainingValueAndPattern() { + thrown.expect( ValueConversionException.class ); + thrown.expectMessage( "\\d+" ); + thrown.expectMessage( "asdf" ); + + new RegexMatcher( "\\d+", 0 ).convert( "asdf" ); + } + + @Test + public void shouldOfferConvenienceMethodForCreatingMatcherWithNoFlags() { + assertEquals( "sourceforge.net", regex( "\\w+\\.\\w+" ).convert( "sourceforge.net" ) ); + } + + @Test + public void shouldAnswerCorrectValueType() { + assertEquals( String.class, abc.valueType() ); + } + + @Test + public void shouldGiveCorrectValuePattern() { + assertEquals( "abc", abc.valuePattern() ); + } +} diff --git a/third_party/java/jopt-simple/src/test/resources/joptsimple/ExceptionMessages_xx_YY.properties b/third_party/java/jopt-simple/src/test/resources/joptsimple/ExceptionMessages_xx_YY.properties new file mode 100644 index 0000000000..ac78a6227b --- /dev/null +++ b/third_party/java/jopt-simple/src/test/resources/joptsimple/ExceptionMessages_xx_YY.properties @@ -0,0 +1,10 @@ +joptsimple.IllegalOptionSpecificationException.message = illegal option specification exception +joptsimple.MissingRequiredOptionsException.message = missing required option exception +joptsimple.MultipleArgumentsForOptionException.message = multiple arguments for option exception +joptsimple.OptionArgumentConversionException.message = option argument conversion exception +joptsimple.OptionMissingRequiredArgumentException.message = option missing required argument exception +joptsimple.UnconfiguredOptionException.message = unconfigured option exception +joptsimple.UnrecognizedOptionException.message = unrecognized option exception +joptsimple.util.DateConverter.without.pattern.message = date converter without pattern +joptsimple.util.DateConverter.with.pattern.message = date converter with pattern +joptsimple.util.RegexMatcher.message = regex matcher
\ No newline at end of file |