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_git_controller_test.rb 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. # Redmine - project management software
  2. # Copyright (C) 2006-2012 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 RepositoriesGitControllerTest < 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/git_repository').to_s
  23. REPOSITORY_PATH.gsub!(/\//, "\\") if Redmine::Platform.mswin?
  24. PRJ_ID = 3
  25. CHAR_1_HEX = "\xc3\x9c"
  26. NUM_REV = 28
  27. ## Git, Mercurial and CVS path encodings are binary.
  28. ## Subversion supports URL encoding for path.
  29. ## Redmine Mercurial adapter and extension use URL encoding.
  30. ## Git accepts only binary path in command line parameter.
  31. ## So, there is no way to use binary command line parameter in JRuby.
  32. JRUBY_SKIP = (RUBY_PLATFORM == 'java')
  33. JRUBY_SKIP_STR = "TODO: This test fails in JRuby"
  34. def setup
  35. @ruby19_non_utf8_pass =
  36. (RUBY_VERSION >= '1.9' && Encoding.default_external.to_s != 'UTF-8')
  37. User.current = nil
  38. @project = Project.find(PRJ_ID)
  39. @repository = Repository::Git.create(
  40. :project => @project,
  41. :url => REPOSITORY_PATH,
  42. :path_encoding => 'ISO-8859-1'
  43. )
  44. assert @repository
  45. @char_1 = CHAR_1_HEX.dup
  46. if @char_1.respond_to?(:force_encoding)
  47. @char_1.force_encoding('UTF-8')
  48. end
  49. Setting.default_language = 'en'
  50. end
  51. def test_create_and_update
  52. @request.session[:user_id] = 1
  53. assert_difference 'Repository.count' do
  54. post :create, :project_id => 'subproject1',
  55. :repository_scm => 'Git',
  56. :repository => {
  57. :url => '/test',
  58. :is_default => '0',
  59. :identifier => 'test-create',
  60. :extra_report_last_commit => '1',
  61. }
  62. end
  63. assert_response 302
  64. repository = Repository.first(:order => 'id DESC')
  65. assert_kind_of Repository::Git, repository
  66. assert_equal '/test', repository.url
  67. assert_equal true, repository.extra_report_last_commit
  68. put :update, :id => repository.id,
  69. :repository => {
  70. :extra_report_last_commit => '0',
  71. :identifier => 'test-update',
  72. }
  73. assert_response 302
  74. repo2 = Repository.find(repository.id)
  75. assert_equal 'test-update', repo2.identifier
  76. assert_equal false, repo2.extra_report_last_commit
  77. end
  78. if File.directory?(REPOSITORY_PATH)
  79. def test_get_new
  80. @request.session[:user_id] = 1
  81. @project.repository.destroy
  82. get :new, :project_id => 'subproject1', :repository_scm => 'Git'
  83. assert_response :success
  84. assert_template 'new'
  85. assert_kind_of Repository::Git, assigns(:repository)
  86. assert assigns(:repository).new_record?
  87. end
  88. def test_browse_root
  89. assert_equal 0, @repository.changesets.count
  90. @repository.fetch_changesets
  91. @project.reload
  92. assert_equal NUM_REV, @repository.changesets.count
  93. get :show, :id => PRJ_ID
  94. assert_response :success
  95. assert_template 'show'
  96. assert_not_nil assigns(:entries)
  97. assert_equal 9, assigns(:entries).size
  98. assert assigns(:entries).detect {|e| e.name == 'images' && e.kind == 'dir'}
  99. assert assigns(:entries).detect {|e| e.name == 'this_is_a_really_long_and_verbose_directory_name' && e.kind == 'dir'}
  100. assert assigns(:entries).detect {|e| e.name == 'sources' && e.kind == 'dir'}
  101. assert assigns(:entries).detect {|e| e.name == 'README' && e.kind == 'file'}
  102. assert assigns(:entries).detect {|e| e.name == 'copied_README' && e.kind == 'file'}
  103. assert assigns(:entries).detect {|e| e.name == 'new_file.txt' && e.kind == 'file'}
  104. assert assigns(:entries).detect {|e| e.name == 'renamed_test.txt' && e.kind == 'file'}
  105. assert assigns(:entries).detect {|e| e.name == 'filemane with spaces.txt' && e.kind == 'file'}
  106. assert assigns(:entries).detect {|e| e.name == ' filename with a leading space.txt ' && e.kind == 'file'}
  107. assert_not_nil assigns(:changesets)
  108. assert assigns(:changesets).size > 0
  109. end
  110. def test_browse_branch
  111. assert_equal 0, @repository.changesets.count
  112. @repository.fetch_changesets
  113. @project.reload
  114. assert_equal NUM_REV, @repository.changesets.count
  115. get :show, :id => PRJ_ID, :rev => 'test_branch'
  116. assert_response :success
  117. assert_template 'show'
  118. assert_not_nil assigns(:entries)
  119. assert_equal 4, assigns(:entries).size
  120. assert assigns(:entries).detect {|e| e.name == 'images' && e.kind == 'dir'}
  121. assert assigns(:entries).detect {|e| e.name == 'sources' && e.kind == 'dir'}
  122. assert assigns(:entries).detect {|e| e.name == 'README' && e.kind == 'file'}
  123. assert assigns(:entries).detect {|e| e.name == 'test.txt' && e.kind == 'file'}
  124. assert_not_nil assigns(:changesets)
  125. assert assigns(:changesets).size > 0
  126. end
  127. def test_browse_tag
  128. assert_equal 0, @repository.changesets.count
  129. @repository.fetch_changesets
  130. @project.reload
  131. assert_equal NUM_REV, @repository.changesets.count
  132. [
  133. "tag00.lightweight",
  134. "tag01.annotated",
  135. ].each do |t1|
  136. get :show, :id => PRJ_ID, :rev => t1
  137. assert_response :success
  138. assert_template 'show'
  139. assert_not_nil assigns(:entries)
  140. assert assigns(:entries).size > 0
  141. assert_not_nil assigns(:changesets)
  142. assert assigns(:changesets).size > 0
  143. end
  144. end
  145. def test_browse_directory
  146. assert_equal 0, @repository.changesets.count
  147. @repository.fetch_changesets
  148. @project.reload
  149. assert_equal NUM_REV, @repository.changesets.count
  150. get :show, :id => PRJ_ID, :path => repository_path_hash(['images'])[:param]
  151. assert_response :success
  152. assert_template 'show'
  153. assert_not_nil assigns(:entries)
  154. assert_equal ['edit.png'], assigns(:entries).collect(&:name)
  155. entry = assigns(:entries).detect {|e| e.name == 'edit.png'}
  156. assert_not_nil entry
  157. assert_equal 'file', entry.kind
  158. assert_equal 'images/edit.png', entry.path
  159. assert_not_nil assigns(:changesets)
  160. assert assigns(:changesets).size > 0
  161. end
  162. def test_browse_at_given_revision
  163. assert_equal 0, @repository.changesets.count
  164. @repository.fetch_changesets
  165. @project.reload
  166. assert_equal NUM_REV, @repository.changesets.count
  167. get :show, :id => PRJ_ID, :path => repository_path_hash(['images'])[:param],
  168. :rev => '7234cb2750b63f47bff735edc50a1c0a433c2518'
  169. assert_response :success
  170. assert_template 'show'
  171. assert_not_nil assigns(:entries)
  172. assert_equal ['delete.png'], assigns(:entries).collect(&:name)
  173. assert_not_nil assigns(:changesets)
  174. assert assigns(:changesets).size > 0
  175. end
  176. def test_changes
  177. get :changes, :id => PRJ_ID,
  178. :path => repository_path_hash(['images', 'edit.png'])[:param]
  179. assert_response :success
  180. assert_template 'changes'
  181. assert_tag :tag => 'h2', :content => 'edit.png'
  182. end
  183. def test_entry_show
  184. get :entry, :id => PRJ_ID,
  185. :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
  186. assert_response :success
  187. assert_template 'entry'
  188. # Line 19
  189. assert_tag :tag => 'th',
  190. :content => '11',
  191. :attributes => { :class => 'line-num' },
  192. :sibling => { :tag => 'td', :content => /WITHOUT ANY WARRANTY/ }
  193. end
  194. def test_entry_show_latin_1
  195. if @ruby19_non_utf8_pass
  196. puts_ruby19_non_utf8_pass()
  197. elsif JRUBY_SKIP
  198. puts JRUBY_SKIP_STR
  199. else
  200. with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
  201. ['57ca437c', '57ca437c0acbbcb749821fdf3726a1367056d364'].each do |r1|
  202. get :entry, :id => PRJ_ID,
  203. :path => repository_path_hash(['latin-1-dir', "test-#{@char_1}.txt"])[:param],
  204. :rev => r1
  205. assert_response :success
  206. assert_template 'entry'
  207. assert_tag :tag => 'th',
  208. :content => '1',
  209. :attributes => { :class => 'line-num' },
  210. :sibling => { :tag => 'td',
  211. :content => /test-#{@char_1}.txt/ }
  212. end
  213. end
  214. end
  215. end
  216. def test_entry_download
  217. get :entry, :id => PRJ_ID,
  218. :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param],
  219. :format => 'raw'
  220. assert_response :success
  221. # File content
  222. assert @response.body.include?('WITHOUT ANY WARRANTY')
  223. end
  224. def test_directory_entry
  225. get :entry, :id => PRJ_ID,
  226. :path => repository_path_hash(['sources'])[:param]
  227. assert_response :success
  228. assert_template 'show'
  229. assert_not_nil assigns(:entry)
  230. assert_equal 'sources', assigns(:entry).name
  231. end
  232. def test_diff
  233. assert_equal 0, @repository.changesets.count
  234. @repository.fetch_changesets
  235. @project.reload
  236. assert_equal NUM_REV, @repository.changesets.count
  237. # Full diff of changeset 2f9c0091
  238. ['inline', 'sbs'].each do |dt|
  239. get :diff,
  240. :id => PRJ_ID,
  241. :rev => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7',
  242. :type => dt
  243. assert_response :success
  244. assert_template 'diff'
  245. # Line 22 removed
  246. assert_tag :tag => 'th',
  247. :content => /22/,
  248. :sibling => { :tag => 'td',
  249. :attributes => { :class => /diff_out/ },
  250. :content => /def remove/ }
  251. assert_tag :tag => 'h2', :content => /2f9c0091/
  252. end
  253. end
  254. def test_diff_truncated
  255. assert_equal 0, @repository.changesets.count
  256. @repository.fetch_changesets
  257. @project.reload
  258. assert_equal NUM_REV, @repository.changesets.count
  259. Setting.diff_max_lines_displayed = 5
  260. # Truncated diff of changeset 2f9c0091
  261. with_cache do
  262. get :diff, :id => PRJ_ID, :type => 'inline',
  263. :rev => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7'
  264. assert_response :success
  265. assert @response.body.include?("... This diff was truncated")
  266. Setting.default_language = 'fr'
  267. get :diff, :id => PRJ_ID, :type => 'inline',
  268. :rev => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7'
  269. assert_response :success
  270. assert ! @response.body.include?("... This diff was truncated")
  271. assert @response.body.include?("... Ce diff")
  272. end
  273. end
  274. def test_diff_two_revs
  275. assert_equal 0, @repository.changesets.count
  276. @repository.fetch_changesets
  277. @project.reload
  278. assert_equal NUM_REV, @repository.changesets.count
  279. ['inline', 'sbs'].each do |dt|
  280. get :diff,
  281. :id => PRJ_ID,
  282. :rev => '61b685fbe55ab05b5ac68402d5720c1a6ac973d1',
  283. :rev_to => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7',
  284. :type => dt
  285. assert_response :success
  286. assert_template 'diff'
  287. diff = assigns(:diff)
  288. assert_not_nil diff
  289. assert_tag :tag => 'h2', :content => /2f9c0091:61b685fb/
  290. end
  291. end
  292. def test_diff_latin_1
  293. if @ruby19_non_utf8_pass
  294. puts_ruby19_non_utf8_pass()
  295. else
  296. with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
  297. ['57ca437c', '57ca437c0acbbcb749821fdf3726a1367056d364'].each do |r1|
  298. ['inline', 'sbs'].each do |dt|
  299. get :diff, :id => PRJ_ID, :rev => r1, :type => dt
  300. assert_response :success
  301. assert_template 'diff'
  302. assert_tag :tag => 'thead',
  303. :descendant => {
  304. :tag => 'th',
  305. :attributes => { :class => 'filename' } ,
  306. :content => /latin-1-dir\/test-#{@char_1}.txt/ ,
  307. },
  308. :sibling => {
  309. :tag => 'tbody',
  310. :descendant => {
  311. :tag => 'td',
  312. :attributes => { :class => /diff_in/ },
  313. :content => /test-#{@char_1}.txt/
  314. }
  315. }
  316. end
  317. end
  318. end
  319. end
  320. end
  321. def test_save_diff_type
  322. @request.session[:user_id] = 1 # admin
  323. user = User.find(1)
  324. get :diff,
  325. :id => PRJ_ID,
  326. :rev => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7'
  327. assert_response :success
  328. assert_template 'diff'
  329. user.reload
  330. assert_equal "inline", user.pref[:diff_type]
  331. get :diff,
  332. :id => PRJ_ID,
  333. :rev => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7',
  334. :type => 'sbs'
  335. assert_response :success
  336. assert_template 'diff'
  337. user.reload
  338. assert_equal "sbs", user.pref[:diff_type]
  339. end
  340. def test_annotate
  341. get :annotate, :id => PRJ_ID,
  342. :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
  343. assert_response :success
  344. assert_template 'annotate'
  345. # Line 24, changeset 2f9c0091
  346. assert_tag :tag => 'th', :content => '24',
  347. :sibling => {
  348. :tag => 'td',
  349. :child => {
  350. :tag => 'a',
  351. :content => /2f9c0091/
  352. }
  353. }
  354. assert_tag :tag => 'th', :content => '24',
  355. :sibling => { :tag => 'td', :content => /jsmith/ }
  356. assert_tag :tag => 'th', :content => '24',
  357. :sibling => {
  358. :tag => 'td',
  359. :child => {
  360. :tag => 'a',
  361. :content => /2f9c0091/
  362. }
  363. }
  364. assert_tag :tag => 'th', :content => '24',
  365. :sibling => { :tag => 'td', :content => /watcher =/ }
  366. end
  367. def test_annotate_at_given_revision
  368. assert_equal 0, @repository.changesets.count
  369. @repository.fetch_changesets
  370. @project.reload
  371. assert_equal NUM_REV, @repository.changesets.count
  372. get :annotate, :id => PRJ_ID, :rev => 'deff7',
  373. :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
  374. assert_response :success
  375. assert_template 'annotate'
  376. assert_tag :tag => 'h2', :content => /@ deff712f/
  377. end
  378. def test_annotate_binary_file
  379. get :annotate, :id => PRJ_ID,
  380. :path => repository_path_hash(['images', 'edit.png'])[:param]
  381. assert_response 500
  382. assert_tag :tag => 'p', :attributes => { :id => /errorExplanation/ },
  383. :content => /cannot be annotated/
  384. end
  385. def test_annotate_error_when_too_big
  386. with_settings :file_max_size_displayed => 1 do
  387. get :annotate, :id => PRJ_ID,
  388. :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param],
  389. :rev => 'deff712f'
  390. assert_response 500
  391. assert_tag :tag => 'p', :attributes => { :id => /errorExplanation/ },
  392. :content => /exceeds the maximum text file size/
  393. get :annotate, :id => PRJ_ID,
  394. :path => repository_path_hash(['README'])[:param],
  395. :rev => '7234cb2'
  396. assert_response :success
  397. assert_template 'annotate'
  398. end
  399. end
  400. def test_annotate_latin_1
  401. if @ruby19_non_utf8_pass
  402. puts_ruby19_non_utf8_pass()
  403. elsif JRUBY_SKIP
  404. puts JRUBY_SKIP_STR
  405. else
  406. with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
  407. ['57ca437c', '57ca437c0acbbcb749821fdf3726a1367056d364'].each do |r1|
  408. get :annotate, :id => PRJ_ID,
  409. :path => repository_path_hash(['latin-1-dir', "test-#{@char_1}.txt"])[:param],
  410. :rev => r1
  411. assert_tag :tag => 'th',
  412. :content => '1',
  413. :attributes => { :class => 'line-num' },
  414. :sibling => { :tag => 'td',
  415. :content => /test-#{@char_1}.txt/ }
  416. end
  417. end
  418. end
  419. end
  420. def test_revision
  421. assert_equal 0, @repository.changesets.count
  422. @repository.fetch_changesets
  423. @project.reload
  424. assert_equal NUM_REV, @repository.changesets.count
  425. ['61b685fbe55ab05b5ac68402d5720c1a6ac973d1', '61b685f'].each do |r|
  426. get :revision, :id => PRJ_ID, :rev => r
  427. assert_response :success
  428. assert_template 'revision'
  429. end
  430. end
  431. def test_empty_revision
  432. assert_equal 0, @repository.changesets.count
  433. @repository.fetch_changesets
  434. @project.reload
  435. assert_equal NUM_REV, @repository.changesets.count
  436. ['', ' ', nil].each do |r|
  437. get :revision, :id => PRJ_ID, :rev => r
  438. assert_response 404
  439. assert_error_tag :content => /was not found/
  440. end
  441. end
  442. def test_destroy_valid_repository
  443. @request.session[:user_id] = 1 # admin
  444. assert_equal 0, @repository.changesets.count
  445. @repository.fetch_changesets
  446. @project.reload
  447. assert_equal NUM_REV, @repository.changesets.count
  448. assert_difference 'Repository.count', -1 do
  449. delete :destroy, :id => @repository.id
  450. end
  451. assert_response 302
  452. @project.reload
  453. assert_nil @project.repository
  454. end
  455. def test_destroy_invalid_repository
  456. @request.session[:user_id] = 1 # admin
  457. @project.repository.destroy
  458. @repository = Repository::Git.create!(
  459. :project => @project,
  460. :url => "/invalid",
  461. :path_encoding => 'ISO-8859-1'
  462. )
  463. @repository.fetch_changesets
  464. @repository.reload
  465. assert_equal 0, @repository.changesets.count
  466. assert_difference 'Repository.count', -1 do
  467. delete :destroy, :id => @repository.id
  468. end
  469. assert_response 302
  470. @project.reload
  471. assert_nil @project.repository
  472. end
  473. private
  474. def puts_ruby19_non_utf8_pass
  475. puts "TODO: This test fails in Ruby 1.9 " +
  476. "and Encoding.default_external is not UTF-8. " +
  477. "Current value is '#{Encoding.default_external.to_s}'"
  478. end
  479. else
  480. puts "Git test repository NOT FOUND. Skipping functional tests !!!"
  481. def test_fake; assert true end
  482. end
  483. private
  484. def with_cache(&block)
  485. before = ActionController::Base.perform_caching
  486. ActionController::Base.perform_caching = true
  487. block.call
  488. ActionController::Base.perform_caching = before
  489. end
  490. end