365 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			V
		
	
	
			
		
		
	
	
			365 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			V
		
	
	
| import flag
 | |
| 
 | |
| fn test_if_flag_not_given_return_default_values() {
 | |
| 	mut fp := flag.new_flag_parser([])
 | |
| 
 | |
| 	assert false == fp.bool('a_bool', 0, false, '')
 | |
| 	&& 42 == fp.int('an_int', 0, 42, '')
 | |
| 	&& 1.0 == fp.float('a_float', 0, 1.0, '')
 | |
| 	&& 'stuff' == fp.string('a_string', 0, 'stuff', '')
 | |
| }
 | |
| 
 | |
| 
 | |
| fn test_could_define_application_name_and_version() {
 | |
| 	mut fp := flag.new_flag_parser([])
 | |
| 	fp.application('test app')
 | |
| 	fp.version('0.0.42')
 | |
| 	fp.description('some text')
 | |
| 
 | |
| 	assert fp.application_name == 'test app'
 | |
| 	&& fp.application_version == '0.0.42'
 | |
| 	&& fp.application_description == 'some text'
 | |
| }
 | |
| 
 | |
| fn test_bool_flags_do_not_need_an_value() {
 | |
| 	mut fp := flag.new_flag_parser(['--a_bool'])
 | |
| 
 | |
| 	assert true == fp.bool('a_bool', 0, false, '')
 | |
| }
 | |
| 
 | |
| fn test_flags_could_be_defined_with_eq() {
 | |
| 	mut fp := flag.new_flag_parser([
 | |
| 	'--an_int=42',
 | |
| 	'--a_float=2.0',
 | |
| 	'--bool_without',
 | |
| 	'--a_string=stuff',
 | |
| 	'--a_bool=true'])
 | |
| 
 | |
| 	assert 42 == fp.int('an_int', 0, 0o666, '')
 | |
| 	&& true == fp.bool('a_bool', 0, false, '')
 | |
| 	&& true == fp.bool('bool_without', 0, false, '')
 | |
| 	&& 2.0 == fp.float('a_float', 0, 1.0, '')
 | |
| 	&& 'stuff' == fp.string('a_string', 0, 'not_stuff', '')
 | |
| }
 | |
| 
 | |
| fn test_values_could_be_defined_without_eq() {
 | |
| 	mut fp := flag.new_flag_parser([
 | |
| 	'--an_int', '42',
 | |
| 	'--a_float', '2.0',
 | |
| 	'--bool_without',
 | |
| 	'--a_string', 'stuff',
 | |
| 	'--a_bool', 'true'])
 | |
| 
 | |
| 	assert 42 == fp.int('an_int', 0, 0o666, '')
 | |
| 	&& true == fp.bool('a_bool', 0, false, '')
 | |
| 	&& true == fp.bool('bool_without', 0, false, '')
 | |
| 	&& 2.0 == fp.float('a_float', 0, 1.0, '')
 | |
| 	&& 'stuff' == fp.string('a_string', 0, 'not_stuff', '')
 | |
| }
 | |
| 
 | |
| fn test_values_could_be_defined_mixed() {
 | |
| 	mut fp := flag.new_flag_parser([
 | |
| 	'--an_int', '42',
 | |
| 	'--a_float=2.0',
 | |
| 	'--bool_without',
 | |
| 	'--a_string', 'stuff',
 | |
| 	'--a_bool=true'])
 | |
| 
 | |
| 	assert 42 == fp.int('an_int', 0, 0o666, '')
 | |
| 	&& true == fp.bool('a_bool', 0, false, '')
 | |
| 	&& true == fp.bool('bool_without', 0, false, '')
 | |
| 	&& 2.0 == fp.float('a_float', 0, 1.0, '')
 | |
| 	&& 'stuff' == fp.string('a_string', 0, 'not_stuff', '')
 | |
| }
 | |
| 
 | |
| fn test_beaware_for_argument_names_with_same_prefix() {
 | |
| 	mut fp := flag.new_flag_parser([
 | |
| 	'--short', '5',
 | |
| 	'--shorter=7'
 | |
| 	])
 | |
| 
 | |
| 	assert 5 == fp.int('short', 0, 0o666, '')
 | |
| 	&& 7 == fp.int('shorter', 0, 0o666, '')
 | |
| }
 | |
| 
 | |
| fn test_beaware_for_argument_names_with_same_prefix_inverse() {
 | |
| 	mut fp := flag.new_flag_parser([
 | |
| 	'--shorter=7',
 | |
| 	'--short', '5',
 | |
| 	])
 | |
| 
 | |
| 	assert 5 == fp.int('short', 0, 0o666, '')
 | |
| 	&& 7 == fp.int('shorter', 0, 0o666, '')
 | |
| }
 | |
| 
 | |
| fn test_allow_to_skip_executable_path() {
 | |
| 	mut fp := flag.new_flag_parser(['./path/to/execuable'])
 | |
| 
 | |
| 	fp.skip_executable()
 | |
| 
 | |
| 	args := fp.finalize() or {
 | |
| 		assert false
 | |
| 		return
 | |
| 	}
 | |
| 	assert !args.contains('./path/to/execuable')
 | |
| }
 | |
| 
 | |
| fn test_none_flag_arguments_are_allowed() {
 | |
| 	mut fp := flag.new_flag_parser([
 | |
| 	'file1', '--an_int=2', 'file2', 'file3', '--bool_without', 'file4', '--outfile', 'outfile'])
 | |
| 
 | |
| 	assert 2 == fp.int('an_int', 0, 0o666, '')
 | |
| 	&& 'outfile' == fp.string('outfile', 0, 'bad', '')
 | |
| 	&& true == fp.bool('bool_without', 0, false, '')
 | |
| }
 | |
| 
 | |
| fn test_finalize_returns_none_flag_arguments_ordered() {
 | |
| 	mut fp := flag.new_flag_parser(['d', 'b', 'x', 'a', '--outfile', 'outfile'])
 | |
| 	fp.string('outfile', 0, 'bad', '')
 | |
| 
 | |
| 	finalized := fp.finalize() or {
 | |
| 		assert false
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	expected := ['d', 'b', 'x', 'a']
 | |
| 	mut all_as_expected := true
 | |
| 	for i, v in finalized {
 | |
| 		all_as_expected = all_as_expected && v == expected[i]
 | |
| 	}
 | |
| 	assert all_as_expected
 | |
| }
 | |
| 
 | |
| fn test_finalize_returns_error_for_unknown_flags() {
 | |
| 	mut fp := flag.new_flag_parser(['--known', '--unknown'])
 | |
| 
 | |
| 	fp.bool('known', 0, false, '')
 | |
| 
 | |
| 	finalized := fp.finalize() or {
 | |
| 		assert err == 'Unknown argument \'unknown\''
 | |
| 		return
 | |
| 	}
 | |
| 	assert finalized.len < 0 // expect error to be returned
 | |
| }
 | |
| 
 | |
| fn test_allow_to_build_usage_message() {
 | |
| 	mut fp := flag.new_flag_parser([])
 | |
| 	fp.limit_free_args(1, 4)
 | |
| 	fp.application('flag_tool')
 | |
| 	fp.version('v0.0.0')
 | |
| 	fp.description('some short information about this tool')
 | |
| 
 | |
| 	fp.int('an_int', 0, 0o666, 'some int to define')
 | |
| 	fp.bool('a_bool', 0, false, 'some bool to define')
 | |
| 	fp.bool('bool_without_but_really_big', 0, false, 'this should appear on the next line')
 | |
| 	fp.float('a_float', 0, 1.0, 'some float as well')
 | |
| 	fp.string('a_string', 0, 'not_stuff', 'your credit card number')
 | |
| 
 | |
| 	usage := fp.usage()
 | |
| 	mut all_strings_found := true
 | |
| 	for s in ['flag_tool', 'v0.0.0',
 | |
| 	'an_int <int>', 'a_bool', 'bool_without', 'a_float <float>', 'a_string <string>',
 | |
| 	'some int to define',
 | |
| 	'some bool to define',
 | |
| 	'this should appear on the next line',
 | |
| 	'some float as well',
 | |
| 	'your credit card number',
 | |
| 	'The arguments should be at least 1 and at most 4 in number.',
 | |
| 	'Usage', 'Options:', 'Description:',
 | |
| 	'some short information about this tool'] {
 | |
| 		if !usage.contains(s) {
 | |
| 			eprintln(' missing \'$s\' in usage message')
 | |
| 			all_strings_found = false
 | |
| 		}
 | |
| 	}
 | |
| 	assert all_strings_found
 | |
| }
 | |
| 
 | |
| fn test_if_no_description_given_usage_message_does_not_contain_descpription() {
 | |
| 	mut fp := flag.new_flag_parser([])
 | |
| 	fp.application('flag_tool')
 | |
| 	fp.version('v0.0.0')
 | |
| 
 | |
| 	fp.bool('a_bool', 0, false, '')
 | |
| 
 | |
| 	assert !fp.usage().contains('Description:')
 | |
| }
 | |
| 
 | |
| fn test_if_no_options_given_usage_message_does_not_contain_options() {
 | |
| 	mut fp := flag.new_flag_parser([])
 | |
| 	fp.application('flag_tool')
 | |
| 	fp.version('v0.0.0')
 | |
| 
 | |
| 	assert !fp.usage().contains('Options:')
 | |
| }
 | |
| 
 | |
| fn test_free_args_could_be_limited() {
 | |
| 	mut fp1 := flag.new_flag_parser(['a', 'b', 'c'])
 | |
| 	fp1.limit_free_args(1, 4)
 | |
| 	args := fp1.finalize() or {
 | |
| 		assert false
 | |
| 		return
 | |
| 	}
 | |
| 	assert args[0] == 'a' && args[1] == 'b' && args[2] == 'c'
 | |
| }
 | |
| 
 | |
| fn test_error_for_to_few_free_args() {
 | |
| 	mut fp1 := flag.new_flag_parser(['a', 'b', 'c'])
 | |
| 	fp1.limit_free_args(5, 6)
 | |
| 	args := fp1.finalize() or {
 | |
| 		assert err.starts_with('Expected at least 5 arguments')
 | |
| 		return
 | |
| 	}
 | |
| 	assert args.len < 0 // expect an error and need to use args
 | |
| }
 | |
| 
 | |
| fn test_error_for_to_much_free_args() {
 | |
| 	mut fp1 := flag.new_flag_parser(['a', 'b', 'c'])
 | |
| 	fp1.limit_free_args(1, 2)
 | |
| 	args := fp1.finalize() or {
 | |
| 		assert err.starts_with('Expected at most 2 arguments')
 | |
| 		return
 | |
| 	}
 | |
| 	assert args.len < 0 // expect an error and need to use args
 | |
| }
 | |
| 
 | |
| fn test_could_expect_no_free_args() {
 | |
| 	mut fp1 := flag.new_flag_parser(['a'])
 | |
| 	fp1.limit_free_args(0, 0)
 | |
| 	args := fp1.finalize() or {
 | |
| 		assert err.starts_with('Expected no arguments')
 | |
| 		return
 | |
| 	}
 | |
| 	assert args.len < 0 // expect an error and need to use args
 | |
| }
 | |
| 
 | |
| fn test_allow_abreviations() {
 | |
| 	mut fp := flag.new_flag_parser(['-v', '-o', 'some_file', '-i', '42', '-f', '2.0'])
 | |
| 
 | |
| 	v := fp.bool('version', `v`, false, '')
 | |
| 	o := fp.string('output', `o`, 'empty', '')
 | |
| 	i := fp.int('count', `i`, 0, '')
 | |
| 	f := fp.float('value', `f`, 0.0, '')
 | |
| 
 | |
| 	assert v && o == 'some_file' && i == 42 && f == 2.0
 | |
| 
 | |
| 	u := fp.usage()
 | |
| 	assert u.contains(' -v') && u.contains(' -o') && u.contains(' -i') && u.contains(' -f')
 | |
| 	assert u.contains('  -o, --output <string>')
 | |
| 	assert u.contains('  -i, --count <int>')
 | |
| 	assert u.contains('  -f, --value <float>')
 | |
| }
 | |
| 
 | |
| fn test_allow_kebab_options() {
 | |
| 	default_value := 'this_is_the_default_value_of_long_option'
 | |
| 	long_option_value := 'this_is_a_long_option_value_as_argument'
 | |
| 
 | |
| 	mut fp := flag.new_flag_parser(['--my-long-flag', 'true', '--my-long-option', long_option_value ])
 | |
| 
 | |
| 	my_flag := fp.bool('my-long-flag', 0, false, 'flag with long-kebab-name')
 | |
| 	my_option := fp.string('my-long-option', 0, default_value, 'string with long-kebab-name')
 | |
| 
 | |
| 	assert my_flag == true
 | |
| 	assert my_option == long_option_value
 | |
| 
 | |
| 	u := fp.usage()
 | |
| 	assert u.contains(' --my-long-flag')
 | |
| 	assert u.contains(' --my-long-option')
 | |
| }
 | |
| 
 | |
| fn test_not_provided_option_is_not_returned() {
 | |
| 	mut fp := flag.new_flag_parser([])
 | |
| 	fp.bool_opt('some-flag', `a`, '') or {
 | |
| 		fp.int_opt('some-flag', `a`, '') or {
 | |
| 			fp.float_opt('some-flag', `a`, '') or {
 | |
| 				fp.string_opt('some-flag', `a`, '') or {
 | |
| 					//Everything should not return
 | |
| 					return
 | |
| 				}
 | |
| 				return
 | |
| 			}
 | |
| 			return
 | |
| 		}
 | |
| 		return
 | |
| 	}
 | |
| 	//If we reach here, one of them returned a value.
 | |
| 	assert false
 | |
| }
 | |
| 
 | |
| fn test_provided_option_is_returned() {
 | |
| 	mut fp := flag.new_flag_parser(['-a', '-b', '3', '-c', 'hello', '-d', '3.14'])
 | |
| 	a := fp.bool_opt('some-flag', `a`, '') or {
 | |
| 		panic('bool_opt did not return a bool')
 | |
| 	}
 | |
| 	b := fp.int_opt('some-flag', `b`, '') or {
 | |
| 		panic('int_opt did not return an int')
 | |
| 	}
 | |
| 	c := fp.string_opt('some-flag', `c`, '') or {
 | |
| 		panic('string_opt did not return a string')
 | |
| 	}
 | |
| 	d := fp.float_opt('some-flag', `d`, '') or {
 | |
| 		panic('float_opt did not return a float')
 | |
| 	}
 | |
| 	assert a && b == 3 && c == 'hello' && d == 3.14
 | |
| }
 | |
| 
 | |
| fn test_multiple_arguments() {
 | |
| 	mut fp := flag.new_flag_parser([
 | |
| 		'-a', '2', '-a', '3', '-a', '5',
 | |
| 		'-b', 'a', '-b', 'c', '-b', 'b',
 | |
| 		'-c', '1.23', '-c', '2.34', '-c', '3.45'
 | |
| 	])
 | |
| 
 | |
| 	//TODO Move to array comparison once it's implemented
 | |
| 	//assert fp.int_multi('some-flag', `a`, '') == [2, 3, 5] &&
 | |
| 	//	fp.string_multi('some-flag', `b`, '') == ['a', 'c', 'b'] &&
 | |
| 	//	fp.float_multi('some-flag', `c`, '') == [1.23, 2.34, 3.45]
 | |
| 
 | |
| 	a := fp.int_multi('some-flag', `a`, '')
 | |
| 	b := fp.string_multi('some-flag', `b`, '')
 | |
| 	c := fp.float_multi('some-flag', `c`, '')
 | |
| 	assert a.len == 3 && b.len == 3 && c.len == 3
 | |
| 	assert a[0] == 2 && a[1] == 3 && a[2] == 5
 | |
| 	assert b[0] == 'a' && b[1] == 'c' && b[2] == 'b'
 | |
| 	assert c[0] == 1.23 && c[1] == 2.34 && c[2] == 3.45
 | |
| }
 | |
| 
 | |
| fn test_long_options_that_start_with_the_same_letter_as_another_short_option() {
 | |
| 	mut fp := flag.new_flag_parser([
 | |
| 		'--vabc', '/abc',
 | |
| 	])
 | |
| 	verbose := fp.bool('verbose', `v`, false, 'Be more verbose.')
 | |
| 	vabc    := fp.string('vabc', `x`, 'default', 'Another option that *may* conflict with v, but *should not*')
 | |
| 	assert verbose == false
 | |
| 	assert vabc == '/abc'
 | |
| }
 | |
| 
 | |
| fn test_long_options_that_start_with_the_same_letter_as_another_short_option_both_set() {
 | |
| 	mut fp := flag.new_flag_parser([
 | |
| 		'-v',
 | |
| 		'--vabc', '/abc',
 | |
| 	])
 | |
| 	verbose := fp.bool('verbose', `v`, false, 'Be more verbose.')
 | |
| 	vabc    := fp.string('vabc', `x`, 'default', 'Another option that *may* conflict with v, but *should not*')
 | |
| 	assert verbose == true
 | |
| 	assert vabc == '/abc'
 | |
| }
 | |
| 
 | |
| fn test_single_dash() {
 | |
| 	mut fp := flag.new_flag_parser([
 | |
| 		'-'
 | |
| 	])
 | |
| 	flag_update := fp.bool('update', `u`, false, 'Update tools')
 | |
| 	assert flag_update == false
 | |
| }
 | |
| 
 | |
| fn test_optional_flags() {
 | |
| 	mut fp := flag.new_flag_parser(['-a', '10', '-b'])
 | |
| 	fp.int_opt('some-flag', `a`, '') or {
 | |
| 		assert false
 | |
| 		return
 | |
| 	}
 | |
| 	b := fp.string_opt('another-flag', `b`, '') or { 'some_default_value' }
 | |
| 	assert b == 'some_default_value'
 | |
| }
 |