#!/usr/bin/env ruby
ENV['RAILS_ENV'] = 'test'
require File.dirname(__FILE__) + '/../config/boot'
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config', 'environment'))
require File.expand_path(File.dirname(__FILE__)) + "/../test/test_helper"

# check for still running daemons from former run
[ '3200', '3201', '3202' ].each do |port|
  begin
    Net::HTTP.start(SOURCE_HOST, 3201) {|http| http.get('/') }
    puts "ERROR Port #{port} is already in use, maybe from former unclean shutdown, aborting ..."
    exit 1
  rescue Errno::ECONNREFUSED, Errno::ENETUNREACH
    # Connect failed, good :)
    next
  end
end

Thread.abort_on_exception = true
srcsrv_out = nil
reposrv_out = nil
servicesrv_out = nil
publishsrv_out = nil
logger = RAILS_DEFAULT_LOGGER
FileUtils.rm_rf("#{RAILS_ROOT}/tmp/backend_data")
FileUtils.rm_rf("#{RAILS_ROOT}/tmp/backend_config")

system("rake db:fixtures:load")

# minimal auth
@http_user = User.find_by_login( "king" )
User.current = @http_user
User.currentID = @http_user.id
User.currentAdmin = @http_user.is_admin?

puts "Creating backend config at #{RAILS_ROOT}/tmp/backend_config/BSConfig.pm"
FileUtils.mkdir "#{RAILS_ROOT}/tmp/backend_config"
file = File.open("#{RAILS_ROOT}/tmp/backend_config/BSConfig.pm", "w")
File.open("#{RAILS_ROOT}/../backend/BSConfig.pm.template") do |template|
  template.readlines.each do |line|
    line.gsub!(/our \$ipaccess/, 'our $ipaccess = undef; our $dummy')
    line.gsub!(/(our \$bsuser)/, '#\1')
    line.gsub!(/(our \$bsgroup)/, '#\1')
    line.gsub!(/our \$bsdir = .*/, "our $bsdir = '#{RAILS_ROOT}/tmp/backend_data';")
    line.gsub!(/our \$servicedir = .*/, "our $servicedir = '#{RAILS_ROOT}/test/fixtures/backend/services';")
    line.gsub!(/:5352/, ":#{SOURCE_PORT}")
    line.gsub!(/:5252/, ":3201") # repservier, used via source server
    line.gsub!(/:5152/, ":3202") # source service, used via source server
    file.print line
  end
end
file.close

perlopts="-I#{RAILS_ROOT}/../backend -I#{RAILS_ROOT}/../backend/build"

%w{bs_srcserver bs_repserver bs_service bs_sched bs_publish}.each do |srv|
  FileUtils.symlink("#{RAILS_ROOT}/../backend/#{srv}", "#{RAILS_ROOT}/tmp/backend_config/#{srv}")
  unless system("cd #{RAILS_ROOT}/tmp/backend_config && exec perl -c #{perlopts} ./#{srv} 2>&1")
    puts "ERROR: syntax broken of #{srv}"
    exit 1
  end
end

puts "Starting backend srcserver..."
srcsrv = Thread.new do
  srcsrv_out = IO.popen("cd #{RAILS_ROOT}/tmp/backend_config; exec perl #{perlopts} ./bs_srcserver 2>&1")
  puts "Started backend srcserver with pid: #{srcsrv_out.pid}"
  begin
    Process.setpgid srcsrv_out.pid, 0
  rescue Errno::EACCES
    puts "Could not set backend srcserver group to root"
    # what to do?
  end
  while srcsrv_out
    begin
      line = srcsrv_out.gets
      logger.debug line.strip unless line.blank?
    rescue IOError
      break
    end
  end
end

puts "Starting backend repserver..."
reposrv = Thread.new do
  reposrv_out = IO.popen("cd #{RAILS_ROOT}/tmp/backend_config; exec perl #{perlopts} ./bs_repserver 2>&1")
  puts "Started backend repserver with pid #{reposrv_out.pid}"
  begin
    Process.setpgid reposrv_out.pid, 0
  rescue Errno::EACCES
    # what to do?
    puts "Could not set backend repserver group to root"
  end
  while reposrv_out
    begin
      line = reposrv_out.gets
      logger.debug line.strip unless line.blank?
    rescue IOError
      break
    end
  end
end

puts "Starting backend serviceserver..."
servicesrv = Thread.new do
  servicesrv_out = IO.popen("cd #{RAILS_ROOT}/tmp/backend_config; exec perl #{perlopts} ./bs_service 2>&1")
  puts "Started backend service server with pid #{servicesrv_out.pid}"
  begin
    Process.setpgid servicesrv_out.pid, 0
  rescue Errno::EACCES
    # what to do?
    puts "Could not set backend serviceserver group to root"
  end
  while servicesrv_out
    begin
      line = servicesrv_out.gets
      logger.debug line.strip unless line.blank?
    rescue IOError
      break
    end
  end
end

puts "Starting backend publisher..."
publishsrv = Thread.new do
  publishsrv_out = IO.popen("cd #{RAILS_ROOT}/tmp/backend_config; exec perl #{perlopts} ./bs_publish 2>&1")
  puts "Started backend publish server with pid #{publishsrv_out.pid}"
  begin
    Process.setpgid publishsrv_out.pid, 0
  rescue Errno::EACCES
    # what to do?
    puts "Could not set backend publish server group to root"
  end
  while publishsrv_out
    begin
      line = publishsrv_out.gets
      logger.debug line.strip unless line.blank?
    rescue IOError
      break
    end
  end
end

while true
  puts "Connecting to srcserver..."
  begin
    Net::HTTP.start(SOURCE_HOST, SOURCE_PORT) {|http| http.get('/') }
  rescue Errno::ECONNREFUSED, Errno::ENETUNREACH
    sleep 0.5
    next
  end
  break
end

while true
  puts "Connecting to repserver..."
  begin
    Net::HTTP.start(SOURCE_HOST, 3201) {|http| http.get('/') }
  rescue Errno::ECONNREFUSED, Errno::ENETUNREACH
    sleep 0.5
    next
  end
  break
end

while true
  puts "Connecting to serviceserver..."
  begin
    Net::HTTP.start(SOURCE_HOST, 3202) {|http| http.get('/') }
  rescue Errno::ECONNREFUSED, Errno::ENETUNREACH
    sleep 0.5
    next
  end
  break
end

Suse::Backend.put( '/issue_trackers', IssueTracker.all.to_xml(IssueTracker::DEFAULT_RENDER_PARAMS))
Suse::Backend.put( '/source/BaseDistro/_meta', DbProject.find_by_name('BaseDistro').to_axml)
Suse::Backend.put( '/source/BaseDistro/_config', "# Empty project config" )
Suse::Backend.put( '/source/BaseDistro/pack1/_meta', DbPackage.find_by_project_and_name("BaseDistro", "pack1").to_axml)
Suse::Backend.put( '/source/BaseDistro/pack1/my_file', "just a file")
Suse::Backend.put( '/source/BaseDistro/pack2/_meta', DbPackage.find_by_project_and_name("BaseDistro", "pack2").to_axml)
Suse::Backend.put( '/source/BaseDistro/pack2/my_file', "different content")
Suse::Backend.put( '/source/BaseDistro/pack2/my_file', "second commit")
Suse::Backend.put( '/source/BaseDistro/pack3/_meta', DbPackage.find_by_project_and_name("BaseDistro", "pack3").to_axml)
Suse::Backend.put( '/source/BaseDistro/pack3/my_file', "just a file")
Suse::Backend.put( '/source/BaseDistro2.0/_meta', DbProject.find_by_name('BaseDistro2.0').to_axml)
Suse::Backend.put( '/source/BaseDistro2.0/_config', "Type: spec" )
Suse::Backend.put( '/source/BaseDistro2.0/pack2/_meta', DbPackage.find_by_id(10099).to_axml)
Suse::Backend.post( '/source/BaseDistro2.0/pack2?cmd=commitfilelist&vrev=2.3&version=1.0', '<directory/>') # set vrev like it get created with makeolder=1
Suse::Backend.put( '/source/BaseDistro2.0/pack2/myfile', "DummyContent of BaseDistro2.0/pack2")
Suse::Backend.put( '/source/BaseDistro2.0/pack2/package.spec',File.open("#{RAILS_ROOT}/test/fixtures/backend/binary/package.spec").read())
Suse::Backend.put( '/source/BaseDistro2.0/pack2_linked/_meta', DbPackage.find_by_id('10100').to_axml)
Suse::Backend.put( '/source/BaseDistro2.0/pack2_linked/_link', "<link package=\"pack2\" cicount='copy' />")
Suse::Backend.put( '/source/BaseDistro2.0:LinkedUpdateProject/_meta', DbProject.find_by_name('BaseDistro2.0:LinkedUpdateProject').to_axml)
Suse::Backend.put( '/source/BaseDistro3/_meta', DbProject.find_by_name('BaseDistro3').to_axml)
Suse::Backend.put( '/source/BaseDistro3/_config', "Type: spec" )
Suse::Backend.put( '/source/BaseDistro3/pack2/_meta', DbPackage.find_by_id('10094').to_axml)
Suse::Backend.put( '/source/BaseDistro3/pack2/package.spec',File.open("#{RAILS_ROOT}/test/fixtures/backend/binary/package.spec").read())
Suse::Backend.put( '/source/Devel:BaseDistro:Update/_meta', DbProject.find_by_name('Devel:BaseDistro:Update').to_axml)
Suse::Backend.put( '/source/BaseDistro:Update/_meta', DbProject.find_by_name('BaseDistro:Update').to_axml)
Suse::Backend.put( '/source/BaseDistro:Update/pack2/_meta', DbPackage.find_by_id(10098).to_axml)
Suse::Backend.put( '/source/BaseDistro:Update/pack2/_link', "<link project=\"BaseDistro\" package=\"pack2\" />")
Suse::Backend.put( '/source/Devel:BaseDistro:Update/pack2/_meta', DbPackage.find_by_project_and_name("Devel:BaseDistro:Update", "pack2").to_axml)
Suse::Backend.put( '/source/Devel:BaseDistro:Update/pack2/_link', "<link project=\"BaseDistro:Update\" package=\"pack2\" />")
Suse::Backend.put( '/source/Devel:BaseDistro:Update/pack2/from_devel_project', "no content")
Suse::Backend.put( '/source/Devel:BaseDistro:Update/pack3/_meta', DbPackage.find_by_project_and_name("Devel:BaseDistro:Update", "pack3").to_axml)
Suse::Backend.put( '/source/Devel:BaseDistro:Update/pack3/_link', "<link project=\"BaseDistro:Update\" package=\"pack3\" />")
Suse::Backend.put( '/source/Devel:BaseDistro:Update/pack3/from_devel_project', "no content")
# HiddenProject (access flag)
Suse::Backend.put( '/source/HiddenProject/_meta', DbProject.find_by_name('HiddenProject').to_axml)
Suse::Backend.put( '/source/HiddenProject/_config', "Type: spec")
Suse::Backend.put( '/source/HiddenProject/pack/_meta', DbPackage.find_by_project_and_name("HiddenProject", "pack").to_axml)
Suse::Backend.put( '/source/HiddenProject/pack/my_file', "Protected Content")
Suse::Backend.put( '/source/HiddenProject/pack/package.spec', File.open("#{RAILS_ROOT}/test/fixtures/backend/binary/package.spec").read())
Suse::Backend.put( '/source/HiddenProject/packCopy/_meta', DbPackage.find_by_project_and_name("HiddenProject", "packCopy").to_axml)
Suse::Backend.put( '/source/HiddenProject/target/_meta', DbPackage.find_by_project_and_name("HiddenProject", "target").to_axml)
Suse::Backend.put( '/source/HiddenProject/target/my_file', "Protected Content target")
# BinaryprotectedProject
Suse::Backend.put( '/source/BinaryprotectedProject/_meta', DbProject.find_by_name('BinaryprotectedProject').to_axml)
Suse::Backend.put( '/source/BinaryprotectedProject/_config', "Type: spec")
Suse::Backend.put( '/source/BinaryprotectedProject/bdpack/_meta', DbPackage.find_by_project_and_name("BinaryprotectedProject", "bdpack").to_axml)
Suse::Backend.put( '/source/BinaryprotectedProject/bdpack/my_file', "Protected Content")
Suse::Backend.put( '/source/BinaryprotectedProject/bdpack/package.spec', File.open("#{RAILS_ROOT}/test/fixtures/backend/binary/package.spec").read())
# SourceaccessProject (sourceaccess flag)
Suse::Backend.put( '/source/SourceprotectedProject/_meta', DbProject.find_by_name('SourceprotectedProject').to_axml)
Suse::Backend.put( '/source/SourceprotectedProject/_config', "Type: spec")
Suse::Backend.put( '/source/SourceprotectedProject/pack/_meta', DbPackage.find_by_project_and_name("SourceprotectedProject", "pack").to_axml)
Suse::Backend.put( '/source/SourceprotectedProject/pack/my_file', "Protected Content")
Suse::Backend.put( '/source/SourceprotectedProject/pack/package.spec', File.open("#{RAILS_ROOT}/test/fixtures/backend/binary/package.spec").read())
Suse::Backend.put( '/source/SourceprotectedProject/target/_meta', DbPackage.find_by_project_and_name("SourceprotectedProject", "target").to_axml)
Suse::Backend.put( '/source/SourceprotectedProject/target/my_file', "Protected Content target")
# Copytest
Suse::Backend.put( '/source/CopyTest/_meta', DbProject.find_by_name('CopyTest').to_axml)
Suse::Backend.put( '/source/CopyTest/_config', "Type: spec")
Suse::Backend.put( '/source/CopyTest/test/_meta', DbPackage.find_by_project_and_name("CopyTest", "test").to_axml)
Suse::Backend.put( '/source/CopyTest/test/my_file', "CopyTest content")
Suse::Backend.put( '/source/CopyTest/test/package.spec', File.open("#{RAILS_ROOT}/test/fixtures/backend/binary/package.spec").read())
Suse::Backend.put( '/source/CopyTest/target/_meta', DbPackage.find_by_project_and_name("CopyTest", "target").to_axml)
# Apache, gets wipe binaries and similar calls
Suse::Backend.put( '/source/Apache/_meta', DbProject.find_by_name('Apache').to_axml)
Suse::Backend.put( '/source/Apache/apache2/_meta', DbPackage.find_by_project_and_name("Apache", "apache2").to_axml)
Suse::Backend.put( '/source/Apache/apache2/my_file', "just a file")

Suse::Backend.put( '/source/RemoteInstance/_meta', DbProject.find_by_name('RemoteInstance').to_axml)
Suse::Backend.put( '/source/LocalProject/_meta', DbProject.find_by_name('LocalProject').to_axml)
Suse::Backend.put( '/source/LocalProject/remotepackage/_meta', DbPackage.find_by_project_and_name("LocalProject", "remotepackage").to_axml)
Suse::Backend.put( '/source/LocalProject/remotepackage/_link', "<link project=\"RemoteInstance:BaseDistro\" package=\"pack1\" />")
Suse::Backend.put( '/source/HiddenRemoteInstance/_meta', DbProject.find_by_name('HiddenRemoteInstance').to_axml)
Suse::Backend.put( '/source/UseRemoteInstance/_meta', DbProject.find_by_name('UseRemoteInstance').to_axml)
Suse::Backend.put( '/source/home:adrian:BaseDistro/_meta', DbProject.find_by_name('home:adrian:BaseDistro').to_axml)
Suse::Backend.put( '/source/home:adrian:ProtectionTest/_meta', DbProject.find_by_name('home:adrian:ProtectionTest').to_axml)
Suse::Backend.put( '/source/home:adrian:ProtectionTest/_config', "Type: spec")
Suse::Backend.put( '/source/home:adrian:ProtectionTest/aggregate/_meta', DbPackage.find_by_id(11200).to_axml)
Suse::Backend.put( '/source/home:adrian:ProtectionTest/aggregate/_aggregate', '<aggregatelist><aggregate project="SourceprotectedProject"><package>pack</package></aggregate></aggregatelist>' )
Suse::Backend.put( '/source/home:coolo/_meta', DbProject.find_by_name('home:coolo').to_axml)
Suse::Backend.put( '/source/home:coolo:test/_meta', DbProject.find_by_name('home:coolo:test').to_axml)
Suse::Backend.put( '/source/home:coolo:test/kdelibs_DEVEL_package/_meta', DbPackage.find_by_name('kdelibs_DEVEL_package').to_axml)
Suse::Backend.put( '/source/home:Iggy/_meta', DbProject.find_by_name('home:Iggy').to_axml)
Suse::Backend.put( '/source/home:Iggy/_config', "Type: spec")
Suse::Backend.put( '/source/home:Iggy/TestPack/_meta', DbPackage.find_by_name('TestPack').to_axml)
Suse::Backend.put( '/source/home:Iggy/TestPack/myfile', "DummyContent")
Suse::Backend.put( '/source/home:Iggy/TestPack/TestPack.spec', File.open("#{RAILS_ROOT}/test/fixtures/backend/source/home:Iggy/TestPack/TestPack.spec").read())
Suse::Backend.put( '/source/home:Iggy/ToBeDeletedTestPack/_meta', DbPackage.find_by_name('ToBeDeletedTestPack').to_axml)
Suse::Backend.put( '/source/home:Iggy:branches:kde4/_meta', DbProject.find_by_name('home:Iggy:branches:kde4').to_axml)
Suse::Backend.put( '/source/home:Iggy:branches:kde4/BranchPack/_meta', DbPackage.find_by_name('BranchPack').to_axml)
Suse::Backend.put( '/source/home:Iggy:branches:kde4/BranchPack/myfile', "DummyContent")
Suse::Backend.put( '/source/home:fred/_meta', DbProject.find_by_name('home:fred').to_axml)
Suse::Backend.put( '/source/home:fred:DeleteProject/_meta', DbProject.find_by_name('home:fred:DeleteProject').to_axml)
Suse::Backend.put( '/source/kde4/_meta', DbProject.find_by_name('kde4').to_axml)
Suse::Backend.put( '/source/kde4/kdebase/_meta', DbPackage.find_by_name('kdebase').to_axml)
Suse::Backend.put( '/source/kde4/kdebase/myfile2', "DummyContent")
Suse::Backend.put( '/source/kde4/kdelibs/_meta', DbPackage.find_by_name('kdelibs').to_axml)
Suse::Backend.put( '/source/kde4/kdelibs/my_patch.diff', 'argl')
Suse::Backend.put( '/source/home:tom/_meta', DbProject.find_by_name('home:tom').to_axml)
Suse::Backend.put( '/source/c%2b%2b/_meta', DbProject.find_by_name('c++').to_axml)
# inject broken requests
system("mkdir -p #{RAILS_ROOT}/tmp/backend_data/requests")
system("echo 1 > #{RAILS_ROOT}/tmp/backend_data/requests/.nextid")
system("cp #{RAILS_ROOT}/test/fixtures/backend/request/missing_source_project #{RAILS_ROOT}/tmp/backend_data/requests/997")
system("cp #{RAILS_ROOT}/test/fixtures/backend/request/missing_target_project #{RAILS_ROOT}/tmp/backend_data/requests/998")
system("cp #{RAILS_ROOT}/test/fixtures/backend/request/missing_projects #{RAILS_ROOT}/tmp/backend_data/requests/999")

# manual placing of files
FileUtils.cp("#{RAILS_ROOT}/test/fixtures/backend/source/_pubkey", "#{RAILS_ROOT}/tmp/backend_data/projects/BaseDistro.pkg/_pubkey")

#
# Prepare backend meta and binary data
#

# run scheduler once
IO.popen("cd #{RAILS_ROOT}/tmp/backend_config; exec perl #{perlopts} ./bs_sched --testmode i586") do |io|
   # just for waiting until scheduler finishes
   io.each {|line| logger.debug line.strip unless line.blank? }
end

# Inject build job results
inject_build_job( "home:Iggy", "TestPack", "10.2", "i586" )
inject_build_job( "HiddenProject", "pack", "nada", "i586" )
inject_build_job( "BinaryprotectedProject", "bdpack", "nada", "i586" )
inject_build_job( "SourceprotectedProject", "pack", "repo", "i586" )

# upload a binary file to repository directly
Suse::Backend.put( '/build/home:Iggy/10.2/i586/_repository/delete_me.rpm?wipe=1', File.open("#{RAILS_ROOT}/test/fixtures/backend/binary/delete_me-1.0-1.i586.rpm").read() )

# run scheduler again to handle the build result
IO.popen("cd #{RAILS_ROOT}/tmp/backend_config; exec perl #{perlopts} ./bs_sched --testmode i586") do |io|
   # just for waiting until scheduler finishes
   io.each {|line| logger.debug line.strip unless line.blank? }
end

# copy build result 
Suse::Backend.post( '/build/HiddenProject/nada/i586/packCopy?cmd=copy&opackage=pack', nil )
Suse::Backend.post( '/build/BaseDistro/BaseDistro_repo/i586/pack2?cmd=copy&oproject=home:Iggy&orepository=10.2&opackage=TestPack', nil )

# run scheduler again to handle the copy build event
IO.popen("cd #{RAILS_ROOT}/tmp/backend_config; exec perl #{perlopts} ./bs_sched --testmode i586") do |io|
   # just for waiting until scheduler finishes
   io.each {|line| logger.debug line.strip unless line.blank? }
end

@http_user = nil
User.current = nil
User.currentID = nil
User.currentAdmin = false

puts "DONE NOW"
$stdout.flush

dienow = false
trap("INT") { dienow = true }

while !dienow do
  sleep 1
end

puts "kill #{srcsrv_out.pid}"
Process.kill "TERM", -srcsrv_out.pid
puts "kill #{reposrv_out.pid}"
Process.kill "TERM", -reposrv_out.pid
puts "kill #{servicesrv_out.pid}"
Process.kill "TERM", -servicesrv_out.pid
puts "kill #{publishsrv_out.pid}"
Process.kill "TERM", -publishsrv_out.pid


srcsrv_out.close
srcsrv_out = nil
srcsrv.join
reposrv_out.close
reposrv_out = nil
reposrv.join
servicesrv_out.close
servicesrv_out = nil
servicesrv.join
publishsrv_out.close
publishsrv_out = nil
publishsrv.join
FileUtils.rm_rf("#{RAILS_ROOT}/tmp/backend_data")
FileUtils.rm_rf("#{RAILS_ROOT}/tmp/backend_config")

