Keyword.t 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use Carp qw{croak};
  5. use Fcm::Keyword::Config;
  6. use Test::More (tests => 227);
  7. BEGIN: {
  8. use_ok('Fcm::Keyword');
  9. }
  10. if (!caller()) {
  11. main(@ARGV);
  12. }
  13. sub main {
  14. local @ARGV = @_;
  15. local %Fcm::Keyword::Config::CONFIG_OF = (
  16. LOCATION_ENTRIES => {entry_class => 'Fcm::Keyword::Entry::Location'},
  17. REVISION_ENTRIES => {entry_class => 'Fcm::Keyword::Entry'},
  18. );
  19. test_get_prefix_of_location_keyword();
  20. test_get_entries();
  21. test_expand();
  22. test_unexpand();
  23. test_get_browser_url();
  24. }
  25. ################################################################################
  26. # Tests get_prefix_of_location_keyword().
  27. sub test_get_prefix_of_location_keyword {
  28. is(Fcm::Keyword::get_prefix_of_location_keyword(), 'fcm');
  29. is(Fcm::Keyword::get_prefix_of_location_keyword(1), 'fcm:');
  30. }
  31. ################################################################################
  32. # Tests get_entries().
  33. sub test_get_entries {
  34. my $entries = Fcm::Keyword::get_entries();
  35. isa_ok($entries, 'Fcm::Keyword::Entries');
  36. for (1 .. 10) {
  37. is(Fcm::Keyword::get_entries(), $entries, "get_entries: is singleton");
  38. }
  39. isnt(Fcm::Keyword::get_entries(1), $entries, "get_entries: can reset");
  40. }
  41. ################################################################################
  42. # Tests expand().
  43. sub test_expand {
  44. my $T = 'expand';
  45. # Add some keywords for testing
  46. _add_keyword_entries([
  47. # ['name' , 'value' , {'rev1' => rev, ...}],
  48. ['FOO' , 'test://foo/foo' , {'V1.0' => 256, 'V1-1' => 4790}],
  49. ['FOO-TR', 'test://foo/foo/trunk', {}],
  50. ]);
  51. _do_keyword_tests($T, \&Fcm::Keyword::expand, [
  52. # Tests to ensure that valid targets are expanded
  53. # [['input' ], ['expected' ]],
  54. [['fcm:FOO' ], ['test://foo/foo' ]],
  55. [['fcm:FOO' , 'V1.0'], ['test://foo/foo' , '256' ]],
  56. [['fcm:Foo' ], ['test://foo/foo' ]],
  57. [['fcm:foo' ], ['test://foo/foo' ]],
  58. [['fcm:foo' , 'v1.0'], ['test://foo/foo' , '256' ]],
  59. [['fcm:foo' , 'head'], ['test://foo/foo' , 'head']],
  60. [['fcm:foo/' ], ['test://foo/foo/' ]],
  61. [['fcm:foo/' , '1234'], ['test://foo/foo/' , '1234']],
  62. [['fcm:foo/' , 'v1.0'], ['test://foo/foo/' , '256' ]],
  63. [['fcm:foo/' , 'v1-1'], ['test://foo/foo/' , '4790']],
  64. [['fcm:foo/bar' ], ['test://foo/foo/bar' ]],
  65. [['fcm:foo/bar' , 'PREV'], ['test://foo/foo/bar' , 'PREV']],
  66. [['fcm:foo/bar' , 'base'], ['test://foo/foo/bar' , 'base']],
  67. [['fcm:foo/bar' , 'v1-1'], ['test://foo/foo/bar' , '4790']],
  68. [['fcm:foo/bar/', '7777'], ['test://foo/foo/bar/' , '7777']],
  69. [['fcm:foo/bar/', '{11}'], ['test://foo/foo/bar/' , '{11}']],
  70. [['fcm:foo/bar/', 'v1.0'], ['test://foo/foo/bar/' , '256' ]],
  71. [['fcm:foo-tr' ], ['test://foo/foo/trunk' ]],
  72. [['fcm:foo-tr' , 'head'], ['test://foo/foo/trunk' , 'head']],
  73. [['fcm:foo-tr' , 'v1.0'], ['test://foo/foo/trunk' , '256' ]],
  74. [['fcm:foo-tr/' ], ['test://foo/foo/trunk/' ]],
  75. [['fcm:foo-tr/' , '1234'], ['test://foo/foo/trunk/', '1234']],
  76. [['fcm:foo-tr/' , 'v1-1'], ['test://foo/foo/trunk/', '4790']],
  77. # Tests to ensure that non-keyword targets are not expanded
  78. # [['input' ]], # 'expected' same as 'input'
  79. [['no-change' ]],
  80. [['foo/bar' ]],
  81. [['/foo/bar' ]],
  82. [['/foo/bar' , 'head' ]],
  83. [['/foo/bar/' ]],
  84. [['/foo/bar/' , 'not-a-key']],
  85. [['svn://foo/bar' ]],
  86. [['svn://foo/bar', '1234' ]],
  87. [['file://foo/bar' ]],
  88. [['http://foo/bar' ]],
  89. ]);
  90. # Tests for unexpected keywords
  91. for my $key (qw{foo bar baz}) {
  92. eval {
  93. Fcm::Keyword::expand("fcm:foo\@$key");
  94. };
  95. isa_ok($@, 'Fcm::Keyword::Exception', "$T: $key: invalid revision");
  96. }
  97. # Tests for "undef", all expecting exceptions
  98. for my $target_ref ([undef], [undef, undef], [undef, 'foo']) {
  99. eval {
  100. Fcm::Keyword::expand(@{$target_ref});
  101. };
  102. isa_ok($@, 'Fcm::Exception', "$T: undef");
  103. }
  104. }
  105. ################################################################################
  106. # Tests unexpand().
  107. sub test_unexpand {
  108. my $T = 'unexpand';
  109. # Add some keywords for testing
  110. _add_keyword_entries([
  111. # ['name' , 'value' , {'rev1' => rev, ...}],
  112. ['FOO' , 'test://foo/foo' , {'V1.0' => 256, 'V1-1' => 4790}],
  113. ['FOO_TR', 'test://foo/foo/trunk', {}],
  114. ['FOO-TR', 'test://foo/foo/trunk', {}],
  115. ]);
  116. _do_keyword_tests($T, \&Fcm::Keyword::unexpand, [
  117. # Tests to ensure that valid targets are expanded
  118. # [['input' ], ['expected' ]],
  119. [['test://foo/foo' ], ['fcm:FOO' ]],
  120. [['test://foo/foo' , '256' ], ['fcm:FOO' , 'V1.0']],
  121. [['test://foo/foo' , 'head'], ['fcm:FOO' , 'head']],
  122. [['test://foo/foo/' ], ['fcm:FOO/' ]],
  123. [['test://foo/foo/' , '1234'], ['fcm:FOO/' , '1234']],
  124. [['test://foo/foo/' , '256' ], ['fcm:FOO/' , 'V1.0']],
  125. [['test://foo/foo/' , '4790'], ['fcm:FOO/' , 'V1-1']],
  126. [['test://foo/foo/bar' ], ['fcm:FOO/bar' ]],
  127. [['test://foo/foo/bar' , 'PREV'], ['fcm:FOO/bar' , 'PREV']],
  128. [['test://foo/foo/bar' , 'base'], ['fcm:FOO/bar' , 'base']],
  129. [['test://foo/foo/bar' , '4790'], ['fcm:FOO/bar' , 'V1-1']],
  130. [['test://foo/foo/bar/' , '7777'], ['fcm:FOO/bar/', '7777']],
  131. [['test://foo/foo/bar/' , '{11}'], ['fcm:FOO/bar/', '{11}']],
  132. [['test://foo/foo/bar/' , '256' ], ['fcm:FOO/bar/', 'V1.0']],
  133. [['test://foo/foo/trunk' ], ['fcm:FOO-TR' ]],
  134. [['test://foo/foo/trunk' , 'head'], ['fcm:FOO-TR' , 'head']],
  135. [['test://foo/foo/trunk' , '256' ], ['fcm:FOO-TR' , 'V1.0']],
  136. [['test://foo/foo/trunk/' ], ['fcm:FOO-TR/' ]],
  137. [['test://foo/foo/trunk/', '1234'], ['fcm:FOO-TR/' , '1234']],
  138. [['test://foo/foo/trunk/', '4790'], ['fcm:FOO-TR/' , 'V1-1']],
  139. # Tests to ensure that non-keyword targets are not expanded
  140. # [['input' ]], # 'expected' same as 'input'
  141. [['no-change' ]],
  142. [['foo/bar' ]],
  143. [['/foo/bar' ]],
  144. [['/foo/bar' , 'head' ]],
  145. [['/foo/bar/' ]],
  146. [['/foo/bar/' , 'not-a-key']],
  147. [['svn://foo/bar' ]],
  148. [['svn://foo/bar', '1234' ]],
  149. [['file://foo/bar' ]],
  150. [['http://foo/bar' ]],
  151. ]);
  152. # Tests for "undef", all expecting exceptions
  153. for my $target_ref ([undef], [undef, undef], [undef, 'foo']) {
  154. eval {
  155. Fcm::Keyword::unexpand(@{$target_ref});
  156. };
  157. isa_ok($@, 'Fcm::Exception', "$T: undef");
  158. }
  159. }
  160. ################################################################################
  161. # Tests get_browser_url().
  162. sub test_get_browser_url {
  163. my $T = 'get_browser_url';
  164. # Add some keywords for testing
  165. _add_keyword_entries([
  166. # ['name' , 'value' , {'rev1' => rev, ...}],
  167. ['FOO' , 'test://foo/foo_svn/foo' , {'V1' => 256, 'W2' => 479}],
  168. ['FOO-TR', 'test://foo/foo_svn/foo/trunk'],
  169. ['FOO_TR', 'test://foo/foo_svn/foo/trunk'],
  170. ]);
  171. my ($INPUT, $EXPECTED) = (0, 1);
  172. my ($LOC, $REV) = (0, 1);
  173. for my $test_ref (
  174. # Tests to ensure that valid targets are expanded
  175. # [['input' ], 'expected' ],
  176. [['test://foo/foo_svn/foo' ], 'http://foo/projects/foo/intertrac/source:foo' ],
  177. [['test://foo/foo_svn/foo' , '256' ], 'http://foo/projects/foo/intertrac/source:foo@256' ],
  178. [['test://foo/foo_svn/foo' , 'head'], 'http://foo/projects/foo/intertrac/source:foo@head' ],
  179. [['test://foo/foo_svn/foo/' ], 'http://foo/projects/foo/intertrac/source:foo/' ],
  180. [['test://foo/foo_svn/foo/' , '1234'], 'http://foo/projects/foo/intertrac/source:foo/@1234' ],
  181. [['test://foo/foo_svn/foo/' , '256' ], 'http://foo/projects/foo/intertrac/source:foo/@256' ],
  182. [['test://foo/foo_svn/foo/' , '479' ], 'http://foo/projects/foo/intertrac/source:foo/@479' ],
  183. [['test://foo/foo_svn/foo/bar' ], 'http://foo/projects/foo/intertrac/source:foo/bar' ],
  184. [['test://foo/foo_svn/foo/bar' , '479' ], 'http://foo/projects/foo/intertrac/source:foo/bar@479' ],
  185. [['test://foo/foo_svn/foo/bar/' , '7777'], 'http://foo/projects/foo/intertrac/source:foo/bar/@7777' ],
  186. [['test://foo/foo_svn/foo/bar/' , '{11}'], 'http://foo/projects/foo/intertrac/source:foo/bar/@{11}' ],
  187. [['test://foo/foo_svn/foo/bar/' , '256' ], 'http://foo/projects/foo/intertrac/source:foo/bar/@256' ],
  188. [['test://foo/foo_svn/foo/trunk' ], 'http://foo/projects/foo/intertrac/source:foo/trunk' ],
  189. [['test://foo/foo_svn/foo/trunk' , 'head'], 'http://foo/projects/foo/intertrac/source:foo/trunk@head' ],
  190. [['test://foo/foo_svn/foo/trunk' , '256' ], 'http://foo/projects/foo/intertrac/source:foo/trunk@256' ],
  191. [['test://foo/foo_svn/foo/trunk/' ], 'http://foo/projects/foo/intertrac/source:foo/trunk/' ],
  192. [['test://foo/foo_svn/foo/trunk/', '1234'], 'http://foo/projects/foo/intertrac/source:foo/trunk/@1234'],
  193. [['test://foo/foo_svn/foo/trunk/', '479' ], 'http://foo/projects/foo/intertrac/source:foo/trunk/@479' ],
  194. [['fcm:FOO' ], 'http://foo/projects/foo/intertrac/source:foo' ],
  195. [['fcm:FOO' , 'V1' ], 'http://foo/projects/foo/intertrac/source:foo@256' ],
  196. [['fcm:FOO' , 'head'], 'http://foo/projects/foo/intertrac/source:foo@head' ],
  197. [['fcm:FOO/' ], 'http://foo/projects/foo/intertrac/source:foo/' ],
  198. [['fcm:FOO/' , '1234'], 'http://foo/projects/foo/intertrac/source:foo/@1234' ],
  199. [['fcm:FOO/' , 'V1' ], 'http://foo/projects/foo/intertrac/source:foo/@256' ],
  200. [['fcm:FOO/' , 'W2' ], 'http://foo/projects/foo/intertrac/source:foo/@479' ],
  201. [['fcm:FOO/bar' ], 'http://foo/projects/foo/intertrac/source:foo/bar' ],
  202. [['fcm:FOO/bar' , 'W2' ], 'http://foo/projects/foo/intertrac/source:foo/bar@479' ],
  203. [['fcm:FOO/bar/' , '7777'], 'http://foo/projects/foo/intertrac/source:foo/bar/@7777' ],
  204. [['fcm:FOO/bar/' , '{11}'], 'http://foo/projects/foo/intertrac/source:foo/bar/@{11}' ],
  205. [['fcm:FOO/bar/' , 'v1' ], 'http://foo/projects/foo/intertrac/source:foo/bar/@256' ],
  206. [['fcm:FOO-TR' ], 'http://foo/projects/foo/intertrac/source:foo/trunk' ],
  207. [['fcm:FOO-TR' , 'head'], 'http://foo/projects/foo/intertrac/source:foo/trunk@head' ],
  208. [['fcm:FOO-TR' , 'V1' ], 'http://foo/projects/foo/intertrac/source:foo/trunk@256' ],
  209. [['fcm:FOO-TR/' ], 'http://foo/projects/foo/intertrac/source:foo/trunk/' ],
  210. [['fcm:FOO-TR/' , '1234'], 'http://foo/projects/foo/intertrac/source:foo/trunk/@1234'],
  211. [['fcm:FOO-TR/' , 'w2' ], 'http://foo/projects/foo/intertrac/source:foo/trunk/@479' ],
  212. ) {
  213. my $input = $test_ref->[$INPUT][$LOC];
  214. if (exists($test_ref->[$INPUT][$REV])) {
  215. $input .= '@' . $test_ref->[$INPUT][$REV];
  216. }
  217. for (
  218. {name => "$T: scalar input: $input", input => [$input]},
  219. {name => "$T: list input: $input" , input => $test_ref->[$INPUT]},
  220. ) {
  221. my $output;
  222. eval {
  223. $output = Fcm::Keyword::get_browser_url(@{$_->{input}});
  224. is($output, $test_ref->[$EXPECTED], $_->{name});
  225. };
  226. if ($@) {
  227. fail("$_->{name}: $@");
  228. }
  229. }
  230. }
  231. # Tests correct behaviour for "undef"
  232. for my $bad_url (undef, '') {
  233. eval {
  234. Fcm::Keyword::get_browser_url($bad_url);
  235. };
  236. isa_ok($@, 'Fcm::Exception', sprintf(
  237. "$T: %s", (defined($bad_url) ? $bad_url : 'undef'),
  238. ));
  239. }
  240. # Tests correct behaviour for invalid inputs
  241. for my $bad_url ('foo', 'svn://no/such/url', 'fcm:no_such_project/trunk') {
  242. eval {
  243. Fcm::Keyword::get_browser_url($bad_url);
  244. };
  245. isa_ok($@, 'Fcm::Keyword::Exception', "$T: $bad_url: invalid keyword");
  246. }
  247. }
  248. ################################################################################
  249. # Adds keyword entries.
  250. sub _add_keyword_entries {
  251. my ($items_ref) = @_;
  252. my ($NAME, $LOC, $REV) = (0 .. 2);
  253. my $entries = Fcm::Keyword::get_entries(1); # reset
  254. for my $item_ref (@{$items_ref}) {
  255. my $entry = $entries->add_entry($item_ref->[$NAME], $item_ref->[$LOC]);
  256. while (my ($key, $value) = each(%{$item_ref->[$REV]})) {
  257. $entry->get_revision_entries()->add_entry($key, $value);
  258. }
  259. }
  260. }
  261. ################################################################################
  262. # Performs keyword testings.
  263. sub _do_keyword_tests {
  264. my ($T, $action_ref, $tests_ref) = @_;
  265. my ($INPUT, $EXPECTED) = (0, 1);
  266. my ($LOC, $REV) = (0, 1);
  267. for my $test_ref (@{$tests_ref}) {
  268. if (!defined($test_ref->[$EXPECTED])) {
  269. $test_ref->[$EXPECTED] = $test_ref->[$INPUT];
  270. }
  271. my %value_of;
  272. for my $i (0 .. $#{$test_ref}) {
  273. $value_of{$i} = $test_ref->[$i][$LOC];
  274. if (exists($test_ref->[$i][$REV])) {
  275. $value_of{$i} .= '@' . $test_ref->[$i][$REV];
  276. }
  277. }
  278. eval {
  279. is(
  280. $action_ref->($value_of{$INPUT}), $value_of{$EXPECTED},
  281. "$T: scalar context: $value_of{$INPUT}",
  282. );
  283. };
  284. if ($@) {
  285. fail("$T: scalar context: $value_of{$INPUT}: $@");
  286. }
  287. eval {
  288. is_deeply(
  289. [$action_ref->(@{$test_ref->[$INPUT]})],
  290. $test_ref->[$EXPECTED],
  291. "$T: list context: $value_of{$INPUT}",
  292. );
  293. };
  294. if ($@) {
  295. fail("$T: list context: $value_of{$INPUT}: $@");
  296. }
  297. }
  298. }
  299. __END__