You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

repositories_mercurial_controller_test.rb 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. # Redmine - project management software
  2. # Copyright (C) 2006-2014 Jean-Philippe Lang
  3. #
  4. # This program is free software; you can redistribute it and/or
  5. # modify it under the terms of the GNU General Public License
  6. # as published by the Free Software Foundation; either version 2
  7. # of the License, or (at your option) any later version.
  8. #
  9. # This program is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. # GNU General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU General Public License
  15. # along with this program; if not, write to the Free Software
  16. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  17. require File.expand_path('../../test_helper', __FILE__)
  18. class RepositoriesMercurialControllerTest < ActionController::TestCase
  19. tests RepositoriesController
  20. fixtures :projects, :users, :roles, :members, :member_roles,
  21. :repositories, :enabled_modules
  22. REPOSITORY_PATH = Rails.root.join('tmp/test/mercurial_repository').to_s
  23. CHAR_1_HEX = "\xc3\x9c"
  24. PRJ_ID = 3
  25. NUM_REV = 34
  26. ruby19_non_utf8_pass =
  27. (RUBY_VERSION >= '1.9' && Encoding.default_external.to_s != 'UTF-8')
  28. def setup
  29. User.current = nil
  30. @project = Project.find(PRJ_ID)
  31. @repository = Repository::Mercurial.create(
  32. :project => @project,
  33. :url => REPOSITORY_PATH,
  34. :path_encoding => 'ISO-8859-1'
  35. )
  36. assert @repository
  37. @diff_c_support = true
  38. @char_1 = CHAR_1_HEX.dup
  39. @tag_char_1 = "tag-#{CHAR_1_HEX}-00"
  40. @branch_char_0 = "branch-#{CHAR_1_HEX}-00"
  41. @branch_char_1 = "branch-#{CHAR_1_HEX}-01"
  42. if @char_1.respond_to?(:force_encoding)
  43. @char_1.force_encoding('UTF-8')
  44. @tag_char_1.force_encoding('UTF-8')
  45. @branch_char_0.force_encoding('UTF-8')
  46. @branch_char_1.force_encoding('UTF-8')
  47. end
  48. end
  49. if ruby19_non_utf8_pass
  50. puts "TODO: Mercurial functional test fails in Ruby 1.9 " +
  51. "and Encoding.default_external is not UTF-8. " +
  52. "Current value is '#{Encoding.default_external.to_s}'"
  53. def test_fake; assert true end
  54. elsif File.directory?(REPOSITORY_PATH)
  55. def test_get_new
  56. @request.session[:user_id] = 1
  57. @project.repository.destroy
  58. get :new, :project_id => 'subproject1', :repository_scm => 'Mercurial'
  59. assert_response :success
  60. assert_template 'new'
  61. assert_kind_of Repository::Mercurial, assigns(:repository)
  62. assert assigns(:repository).new_record?
  63. end
  64. def test_show_root
  65. assert_equal 0, @repository.changesets.count
  66. @repository.fetch_changesets
  67. @project.reload
  68. assert_equal NUM_REV, @repository.changesets.count
  69. get :show, :id => PRJ_ID
  70. assert_response :success
  71. assert_template 'show'
  72. assert_not_nil assigns(:entries)
  73. assert_equal 4, assigns(:entries).size
  74. assert assigns(:entries).detect {|e| e.name == 'images' && e.kind == 'dir'}
  75. assert assigns(:entries).detect {|e| e.name == 'sources' && e.kind == 'dir'}
  76. assert assigns(:entries).detect {|e| e.name == 'README' && e.kind == 'file'}
  77. assert_not_nil assigns(:changesets)
  78. assert assigns(:changesets).size > 0
  79. end
  80. def test_show_directory
  81. assert_equal 0, @repository.changesets.count
  82. @repository.fetch_changesets
  83. @project.reload
  84. assert_equal NUM_REV, @repository.changesets.count
  85. get :show, :id => PRJ_ID, :path => repository_path_hash(['images'])[:param]
  86. assert_response :success
  87. assert_template 'show'
  88. assert_not_nil assigns(:entries)
  89. assert_equal ['delete.png', 'edit.png'], assigns(:entries).collect(&:name)
  90. entry = assigns(:entries).detect {|e| e.name == 'edit.png'}
  91. assert_not_nil entry
  92. assert_equal 'file', entry.kind
  93. assert_equal 'images/edit.png', entry.path
  94. assert_not_nil assigns(:changesets)
  95. assert assigns(:changesets).size > 0
  96. end
  97. def test_show_at_given_revision
  98. assert_equal 0, @repository.changesets.count
  99. @repository.fetch_changesets
  100. @project.reload
  101. assert_equal NUM_REV, @repository.changesets.count
  102. [0, '0', '0885933ad4f6'].each do |r1|
  103. get :show, :id => PRJ_ID, :path => repository_path_hash(['images'])[:param],
  104. :rev => r1
  105. assert_response :success
  106. assert_template 'show'
  107. assert_not_nil assigns(:entries)
  108. assert_equal ['delete.png'], assigns(:entries).collect(&:name)
  109. assert_not_nil assigns(:changesets)
  110. assert assigns(:changesets).size > 0
  111. end
  112. end
  113. def test_show_directory_sql_escape_percent
  114. assert_equal 0, @repository.changesets.count
  115. @repository.fetch_changesets
  116. @project.reload
  117. assert_equal NUM_REV, @repository.changesets.count
  118. [13, '13', '3a330eb32958'].each do |r1|
  119. get :show, :id => PRJ_ID,
  120. :path => repository_path_hash(['sql_escape', 'percent%dir'])[:param],
  121. :rev => r1
  122. assert_response :success
  123. assert_template 'show'
  124. assert_not_nil assigns(:entries)
  125. assert_equal ['percent%file1.txt', 'percentfile1.txt'],
  126. assigns(:entries).collect(&:name)
  127. changesets = assigns(:changesets)
  128. assert_not_nil changesets
  129. assert assigns(:changesets).size > 0
  130. assert_equal %w(13 11 10 9), changesets.collect(&:revision)
  131. end
  132. end
  133. def test_show_directory_latin_1_path
  134. assert_equal 0, @repository.changesets.count
  135. @repository.fetch_changesets
  136. @project.reload
  137. assert_equal NUM_REV, @repository.changesets.count
  138. [21, '21', 'adf805632193'].each do |r1|
  139. get :show, :id => PRJ_ID,
  140. :path => repository_path_hash(['latin-1-dir'])[:param],
  141. :rev => r1
  142. assert_response :success
  143. assert_template 'show'
  144. assert_not_nil assigns(:entries)
  145. assert_equal ["make-latin-1-file.rb",
  146. "test-#{@char_1}-1.txt",
  147. "test-#{@char_1}-2.txt",
  148. "test-#{@char_1}.txt"], assigns(:entries).collect(&:name)
  149. changesets = assigns(:changesets)
  150. assert_not_nil changesets
  151. assert_equal %w(21 20 19 18 17), changesets.collect(&:revision)
  152. end
  153. end
  154. def show_should_show_branch_selection_form
  155. @repository.fetch_changesets
  156. @project.reload
  157. get :show, :id => PRJ_ID
  158. assert_tag 'form', :attributes => {:id => 'revision_selector', :action => '/projects/subproject1/repository/show'}
  159. assert_tag 'select', :attributes => {:name => 'branch'},
  160. :child => {:tag => 'option', :attributes => {:value => 'test-branch-01'}},
  161. :parent => {:tag => 'form', :attributes => {:id => 'revision_selector'}}
  162. end
  163. def test_show_branch
  164. assert_equal 0, @repository.changesets.count
  165. @repository.fetch_changesets
  166. @project.reload
  167. assert_equal NUM_REV, @repository.changesets.count
  168. [
  169. 'default',
  170. @branch_char_1,
  171. 'branch (1)[2]&,%.-3_4',
  172. @branch_char_0,
  173. 'test_branch.latin-1',
  174. 'test-branch-00',
  175. ].each do |bra|
  176. get :show, :id => PRJ_ID, :rev => bra
  177. assert_response :success
  178. assert_template 'show'
  179. assert_not_nil assigns(:entries)
  180. assert assigns(:entries).size > 0
  181. assert_not_nil assigns(:changesets)
  182. assert assigns(:changesets).size > 0
  183. end
  184. end
  185. def test_show_tag
  186. assert_equal 0, @repository.changesets.count
  187. @repository.fetch_changesets
  188. @project.reload
  189. assert_equal NUM_REV, @repository.changesets.count
  190. [
  191. @tag_char_1,
  192. 'tag_test.00',
  193. 'tag-init-revision'
  194. ].each do |tag|
  195. get :show, :id => PRJ_ID, :rev => tag
  196. assert_response :success
  197. assert_template 'show'
  198. assert_not_nil assigns(:entries)
  199. assert assigns(:entries).size > 0
  200. assert_not_nil assigns(:changesets)
  201. assert assigns(:changesets).size > 0
  202. end
  203. end
  204. def test_changes
  205. get :changes, :id => PRJ_ID,
  206. :path => repository_path_hash(['images', 'edit.png'])[:param]
  207. assert_response :success
  208. assert_template 'changes'
  209. assert_tag :tag => 'h2', :content => 'edit.png'
  210. end
  211. def test_entry_show
  212. get :entry, :id => PRJ_ID,
  213. :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
  214. assert_response :success
  215. assert_template 'entry'
  216. # Line 10
  217. assert_tag :tag => 'th',
  218. :content => '10',
  219. :attributes => { :class => 'line-num' },
  220. :sibling => { :tag => 'td', :content => /WITHOUT ANY WARRANTY/ }
  221. end
  222. def test_entry_show_latin_1_path
  223. [21, '21', 'adf805632193'].each do |r1|
  224. get :entry, :id => PRJ_ID,
  225. :path => repository_path_hash(['latin-1-dir', "test-#{@char_1}-2.txt"])[:param],
  226. :rev => r1
  227. assert_response :success
  228. assert_template 'entry'
  229. assert_tag :tag => 'th',
  230. :content => '1',
  231. :attributes => { :class => 'line-num' },
  232. :sibling => { :tag => 'td',
  233. :content => /Mercurial is a distributed version control system/ }
  234. end
  235. end
  236. def test_entry_show_latin_1_contents
  237. with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
  238. [27, '27', '7bbf4c738e71'].each do |r1|
  239. get :entry, :id => PRJ_ID,
  240. :path => repository_path_hash(['latin-1-dir', "test-#{@char_1}.txt"])[:param],
  241. :rev => r1
  242. assert_response :success
  243. assert_template 'entry'
  244. assert_tag :tag => 'th',
  245. :content => '1',
  246. :attributes => { :class => 'line-num' },
  247. :sibling => { :tag => 'td',
  248. :content => /test-#{@char_1}.txt/ }
  249. end
  250. end
  251. end
  252. def test_entry_download
  253. get :entry, :id => PRJ_ID,
  254. :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param],
  255. :format => 'raw'
  256. assert_response :success
  257. # File content
  258. assert @response.body.include?('WITHOUT ANY WARRANTY')
  259. end
  260. def test_entry_binary_force_download
  261. get :entry, :id => PRJ_ID, :rev => 1,
  262. :path => repository_path_hash(['images', 'edit.png'])[:param]
  263. assert_response :success
  264. assert_equal 'image/png', @response.content_type
  265. end
  266. def test_directory_entry
  267. get :entry, :id => PRJ_ID,
  268. :path => repository_path_hash(['sources'])[:param]
  269. assert_response :success
  270. assert_template 'show'
  271. assert_not_nil assigns(:entry)
  272. assert_equal 'sources', assigns(:entry).name
  273. end
  274. def test_diff
  275. assert_equal 0, @repository.changesets.count
  276. @repository.fetch_changesets
  277. @project.reload
  278. assert_equal NUM_REV, @repository.changesets.count
  279. [4, '4', 'def6d2f1254a'].each do |r1|
  280. # Full diff of changeset 4
  281. ['inline', 'sbs'].each do |dt|
  282. get :diff, :id => PRJ_ID, :rev => r1, :type => dt
  283. assert_response :success
  284. assert_template 'diff'
  285. if @diff_c_support
  286. # Line 22 removed
  287. assert_tag :tag => 'th',
  288. :content => '22',
  289. :sibling => { :tag => 'td',
  290. :attributes => { :class => /diff_out/ },
  291. :content => /def remove/ }
  292. assert_tag :tag => 'h2', :content => /4:def6d2f1254a/
  293. end
  294. end
  295. end
  296. end
  297. def test_diff_two_revs
  298. assert_equal 0, @repository.changesets.count
  299. @repository.fetch_changesets
  300. @project.reload
  301. assert_equal NUM_REV, @repository.changesets.count
  302. [2, '400bb8672109', '400', 400].each do |r1|
  303. [4, 'def6d2f1254a'].each do |r2|
  304. ['inline', 'sbs'].each do |dt|
  305. get :diff,
  306. :id => PRJ_ID,
  307. :rev => r1,
  308. :rev_to => r2,
  309. :type => dt
  310. assert_response :success
  311. assert_template 'diff'
  312. diff = assigns(:diff)
  313. assert_not_nil diff
  314. assert_tag :tag => 'h2',
  315. :content => /4:def6d2f1254a 2:400bb8672109/
  316. end
  317. end
  318. end
  319. end
  320. def test_diff_latin_1_path
  321. with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
  322. [21, 'adf805632193'].each do |r1|
  323. ['inline', 'sbs'].each do |dt|
  324. get :diff, :id => PRJ_ID, :rev => r1, :type => dt
  325. assert_response :success
  326. assert_template 'diff'
  327. assert_tag :tag => 'thead',
  328. :descendant => {
  329. :tag => 'th',
  330. :attributes => { :class => 'filename' } ,
  331. :content => /latin-1-dir\/test-#{@char_1}-2.txt/ ,
  332. },
  333. :sibling => {
  334. :tag => 'tbody',
  335. :descendant => {
  336. :tag => 'td',
  337. :attributes => { :class => /diff_in/ },
  338. :content => /It is written in Python/
  339. }
  340. }
  341. end
  342. end
  343. end
  344. end
  345. def test_diff_should_show_modified_filenames
  346. get :diff, :id => PRJ_ID, :rev => '400bb8672109', :type => 'inline'
  347. assert_response :success
  348. assert_template 'diff'
  349. assert_select 'th.filename', :text => 'sources/watchers_controller.rb'
  350. end
  351. def test_diff_should_show_deleted_filenames
  352. get :diff, :id => PRJ_ID, :rev => 'b3a615152df8', :type => 'inline'
  353. assert_response :success
  354. assert_template 'diff'
  355. assert_select 'th.filename', :text => 'sources/welcome_controller.rb'
  356. end
  357. def test_annotate
  358. get :annotate, :id => PRJ_ID,
  359. :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
  360. assert_response :success
  361. assert_template 'annotate'
  362. # Line 22, revision 4:def6d2f1254a
  363. assert_select 'tr' do
  364. assert_select 'th.line-num', :text => '22'
  365. assert_select 'td.revision', :text => '4:def6d2f1254a'
  366. assert_select 'td.author', :text => 'jsmith'
  367. assert_select 'td', :text => /remove_watcher/
  368. end
  369. end
  370. def test_annotate_not_in_tip
  371. assert_equal 0, @repository.changesets.count
  372. @repository.fetch_changesets
  373. @project.reload
  374. assert_equal NUM_REV, @repository.changesets.count
  375. get :annotate, :id => PRJ_ID,
  376. :path => repository_path_hash(['sources', 'welcome_controller.rb'])[:param]
  377. assert_response 404
  378. assert_error_tag :content => /was not found/
  379. end
  380. def test_annotate_at_given_revision
  381. assert_equal 0, @repository.changesets.count
  382. @repository.fetch_changesets
  383. @project.reload
  384. assert_equal NUM_REV, @repository.changesets.count
  385. [2, '400bb8672109', '400', 400].each do |r1|
  386. get :annotate, :id => PRJ_ID, :rev => r1,
  387. :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
  388. assert_response :success
  389. assert_template 'annotate'
  390. assert_tag :tag => 'h2', :content => /@ 2:400bb8672109/
  391. end
  392. end
  393. def test_annotate_latin_1_path
  394. [21, '21', 'adf805632193'].each do |r1|
  395. get :annotate, :id => PRJ_ID,
  396. :path => repository_path_hash(['latin-1-dir', "test-#{@char_1}-2.txt"])[:param],
  397. :rev => r1
  398. assert_response :success
  399. assert_template 'annotate'
  400. assert_select "th.line-num", :text => '1' do
  401. assert_select "+ td.revision" do
  402. assert_select "a", :text => '20:709858aafd1b'
  403. assert_select "+ td.author", :text => "jsmith" do
  404. assert_select "+ td",
  405. :text => "Mercurial is a distributed version control system."
  406. end
  407. end
  408. end
  409. end
  410. end
  411. def test_annotate_latin_1_contents
  412. with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
  413. [27, '7bbf4c738e71'].each do |r1|
  414. get :annotate, :id => PRJ_ID,
  415. :path => repository_path_hash(['latin-1-dir', "test-#{@char_1}.txt"])[:param],
  416. :rev => r1
  417. assert_tag :tag => 'th',
  418. :content => '1',
  419. :attributes => { :class => 'line-num' },
  420. :sibling => { :tag => 'td',
  421. :content => /test-#{@char_1}.txt/ }
  422. end
  423. end
  424. end
  425. def test_revision
  426. assert_equal 0, @repository.changesets.count
  427. @repository.fetch_changesets
  428. @project.reload
  429. assert_equal NUM_REV, @repository.changesets.count
  430. ['1', '9d5b5b', '9d5b5b004199'].each do |r|
  431. with_settings :default_language => "en" do
  432. get :revision, :id => PRJ_ID, :rev => r
  433. assert_response :success
  434. assert_template 'revision'
  435. assert_select 'title',
  436. :text => 'Revision 1:9d5b5b004199 - Added 2 files and modified one. - eCookbook Subproject 1 - Redmine'
  437. end
  438. end
  439. end
  440. def test_empty_revision
  441. assert_equal 0, @repository.changesets.count
  442. @repository.fetch_changesets
  443. @project.reload
  444. assert_equal NUM_REV, @repository.changesets.count
  445. ['', ' ', nil].each do |r|
  446. get :revision, :id => PRJ_ID, :rev => r
  447. assert_response 404
  448. assert_error_tag :content => /was not found/
  449. end
  450. end
  451. def test_destroy_valid_repository
  452. @request.session[:user_id] = 1 # admin
  453. assert_equal 0, @repository.changesets.count
  454. @repository.fetch_changesets
  455. assert_equal NUM_REV, @repository.changesets.count
  456. assert_difference 'Repository.count', -1 do
  457. delete :destroy, :id => @repository.id
  458. end
  459. assert_response 302
  460. @project.reload
  461. assert_nil @project.repository
  462. end
  463. def test_destroy_invalid_repository
  464. @request.session[:user_id] = 1 # admin
  465. @project.repository.destroy
  466. @repository = Repository::Mercurial.create!(
  467. :project => Project.find(PRJ_ID),
  468. :url => "/invalid",
  469. :path_encoding => 'ISO-8859-1'
  470. )
  471. @repository.fetch_changesets
  472. assert_equal 0, @repository.changesets.count
  473. assert_difference 'Repository.count', -1 do
  474. delete :destroy, :id => @repository.id
  475. end
  476. assert_response 302
  477. @project.reload
  478. assert_nil @project.repository
  479. end
  480. else
  481. puts "Mercurial test repository NOT FOUND. Skipping functional tests !!!"
  482. def test_fake; assert true end
  483. end
  484. end