summaryrefslogtreecommitdiff
path: root/rdiff-backup/testing/killtest.py
blob: 7c157af52b4b12eb8fdf970b8ba7851cdd409ab4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import unittest, os, signal, sys, random, time
execfile("commontest.py")
rbexec("restore.py")

"""Test consistency by killing rdiff-backup as it is backing up"""

Log.setverbosity(3)

class Local:
	"""Hold some local RPaths"""
	def get_local_rp(ext):
		return RPath(Globals.local_connection, "testfiles/" + ext)

	inc1rp = get_local_rp('increment1')
	inc2rp = get_local_rp('increment2')
	inc3rp = get_local_rp('increment3')
	inc4rp = get_local_rp('increment4')

	rpout = get_local_rp('output')
	rpout_inc = get_local_rp('output_inc')
	rpout1 = get_local_rp('restoretarget1')
	rpout2 = get_local_rp('restoretarget2')
	rpout3 = get_local_rp('restoretarget3')
	rpout4 = get_local_rp('restoretarget4')

	back1 = get_local_rp('backup1')
	back2 = get_local_rp('backup2')
	back3 = get_local_rp('backup3')
	back4 = get_local_rp('backup4')


class Kill(unittest.TestCase):
	def delete_tmpdirs(self):
		"""Remove any temp directories created by previous tests"""
		assert not os.system(MiscDir + '/myrm testfiles/output* '
							 'testfiles/restoretarget* testfiles/vft_out '
							 'timbar.pyc testfiles/vft2_out')

	def is_aborted_backup(self):
		"""True if there are signs of aborted backup in output/"""
		try: dirlist = os.listdir("testfiles/output/rdiff-backup-data")
		except OSError:
			print "No data dir found, give process more time"
			raise
		dirlist = filter(lambda f: f.startswith("last-file-incremented"),
						 dirlist)
		return len(dirlist) != 0

	def exec_rb(self, time, wait, *args):
		"""Run rdiff-backup return pid"""
		arglist = ['python', '../src/rdiff-backup', '-v7']
		if time:
			arglist.append("--current-time")
			arglist.append(str(time))
		arglist.extend(args)

		print "Running ", arglist
		if wait: return os.spawnvp(os.P_WAIT, 'python', arglist)
		else: return os.spawnvp(os.P_NOWAIT, 'python', arglist)

	def exec_and_kill(self, mintime, maxtime, backup_time, *args):
		"""Run rdiff-backup, then kill and run again

		Kill after a time between mintime and maxtime.  First process
		should not terminate before maxtime.

		"""
		pid = self.exec_rb(backup_time, None, *args)
		time.sleep(random.uniform(mintime, maxtime))
		assert os.waitpid(pid, os.WNOHANG)[0] == 0, \
			   "Process already quit - try lowering max time"
		os.kill(pid, self.killsignal)
		while 1:
			pid, exitstatus = os.waitpid(pid, os.WNOHANG)
			if pid:
				assert exitstatus != 0
				break
			time.sleep(0.2)
		assert self.is_aborted_backup(), \
			   "Process already finished or didn't get a chance to start"
		os.system("ls -l %s/rdiff-backup-data" % args[1])
		return self.exec_rb(backup_time + 5, 1, '--resume', *args)

	def verify_back_dirs(self):
		"""Make sure testfiles/output/back? dirs exist"""
		if (Local.back1.lstat() and Local.back2.lstat() and
			Local.back3.lstat() and Local.back4.lstat()): return

		os.system(MiscDir + "/myrm testfiles/backup[1-4]")

		self.exec_rb(10000, 1, 'testfiles/increment1', 'testfiles/backup1')
		Local.back1.setdata()

		self.exec_rb(10000, 1, 'testfiles/increment1', 'testfiles/backup2')
		self.exec_rb(20000, 1, 'testfiles/increment2', 'testfiles/backup2')
		Local.back2.setdata()
		
		self.exec_rb(10000, 1, 'testfiles/increment1', 'testfiles/backup3')
		self.exec_rb(20000, 1, 'testfiles/increment2', 'testfiles/backup3')
		self.exec_rb(30000, 1, 'testfiles/increment3', 'testfiles/backup3')
		Local.back3.setdata()
		
		self.exec_rb(10000, 1, 'testfiles/increment1', 'testfiles/backup4')
		self.exec_rb(20000, 1, 'testfiles/increment2', 'testfiles/backup4')
		self.exec_rb(30000, 1, 'testfiles/increment3', 'testfiles/backup4')
		self.exec_rb(40000, 1, 'testfiles/increment4', 'testfiles/backup4')
		Local.back4.setdata()

	def runtest(self):
		self.delete_tmpdirs()
		self.verify_back_dirs()
		
		# Backing up increment1 - unfortunately, not big enough to test?
		#self.exec_and_kill(0.6, 0.6, 10000,
		#				   'testfiles/increment1', 'testfiles/output')
		#assert CompareRecursive(Local.back1, Local.rpout, 1, None, None)
		self.exec_rb(10000, 1, 'testfiles/increment1', 'testfiles/output')
		time.sleep(1)

		# Backing up increment2
		self.exec_and_kill(0.7, 1.0, 20000,
						   'testfiles/increment2', 'testfiles/output')
		assert CompareRecursive(Local.back2, Local.rpout, 1, None, None)
		time.sleep(1)

		# Backing up increment3
		self.exec_and_kill(0.7, 2.0, 30000,
						   'testfiles/increment3', 'testfiles/output')
		assert CompareRecursive(Local.back3, Local.rpout, 1, None, None)
		time.sleep(1)

		# Backing up increment4
		self.exec_and_kill(1.0, 5.0, 40000,
						   'testfiles/increment4', 'testfiles/output')
		assert CompareRecursive(Local.back4, Local.rpout, 1, None, None)

	def testTERM(self):
		"""Test sending local processes a TERM signal"""
		self.killsignal = signal.SIGTERM
		for i in range(5):
			self.runtest()

	def testKILL(self):
		"""Send local backup process a KILL signal"""
		self.killsignal = signal.SIGKILL
		self.runtest()

if __name__ == "__main__": unittest.main()