def testConditionsSweep(self):
		"""
		Tests a setup with condition variables and output variables.  Similar to testProper, but with
		conditions mixed in.
		"""

		res_bufs = [[], [], [], []]
		measurement_counts = [0] * 2

		def setter(i, value):
			res_bufs[i].append(value)

		def getter(i):
			measurement_counts[i] += (-1) ** i

			return measurement_counts[i]

		dwell_time = Quantity(50, 'ms')

		# Output.
		res0 = Resource(setter=partial(setter, 0))
		res0.units = 'cm-1'
		res1 = Resource(setter=partial(setter, 1))
		res2 = Resource(setter=partial(setter, 2))
		res3 = Resource(setter=partial(setter, 3))

		var0 = OutputVariable(name='Var 0', order=2, enabled=True, const=0.0)
		var0.config = LinSpaceConfig(-1.0, -2.0, 2)
		var0.smooth_steps = 2
		var0.smooth_from, var0.smooth_to, var0.smooth_transition = [True] * 3
		var0.type = 'quantity'
		var0.units = 'cm-1'

		var1 = OutputVariable(name='Var 1', order=1, enabled=True, const=-1.0)
		var1.config = LinSpaceConfig(1.0, 4.0, 4)
		var1.smooth_steps = 3
		var1.smooth_from, var1.smooth_to, var1.smooth_transition = [True] * 3

		var2 = OutputVariable(name='Var 2', order=1, enabled=True, const=1.23, use_const=True)

		var3 = OutputVariable(name='Var 3', order=1, enabled=True, const=-9.0, wait=str(dwell_time))
		var3.config = LinSpaceConfig(-1.0, 2.0, 4)
		var3.smooth_steps = 2
		var3.smooth_from, var3.smooth_to, var3.smooth_transition = True, True, False

		var4 = OutputVariable(name='Var 4', order=3, enabled=True, const=-20.0)
		var4.config = LinSpaceConfig(-10.0, 20, 1)
		var4.smooth_steps = 2
		var4.smooth_from = True
		
		# Condition variables.
		
		## Resources used for checking the conditions.
		
		iters = [cycle([0,1]), cycle([0,1,2]), cycle([0,-1,-2])]
		def cres_getter(i):
			return iters[i].next()
				
		cres0 = Resource('cres0', getter=partial(cres_getter,0))
		cres1 = Resource('cres1', getter=partial(cres_getter,1))
		cres2 = Resource('cres2', getter=partial(cres_getter,2))
		
		condition_resources = [(('cres0',cres0),),(('cres1',cres1),('cres2',cres2),)]
		
		
		cond0 = Condition('resource name','integer','cres0','==',1)
		cond1 = Condition('resource name','integer','cres1','==',2)
		cond2 = Condition('resource name','integer','cres2','==',-2)

		cvar0 = ConditionVariable(name='cvar0',order=0,enabled=True,wait=str(dwell_time),
								resource_names=['cres0',],conditions=[cond0])
		cvar1 = ConditionVariable(name='cvar1',order=1,enabled=True,wait=str(dwell_time),
								resource_names=['cres1',],conditions=[cond1])
		cvar2 = ConditionVariable(name='cvar2',order=1,enabled=True,wait=str(dwell_time),
								resource_names=['cres2',],conditions=[cond2])

		# Input.
		meas_res0 = Resource(getter=partial(getter, 0))
		meas_res1 = Resource(getter=partial(getter, 1))

		meas0 = InputVariable(name='Meas 0')
		meas1 = InputVariable(name='Meas 1')

		vars, num_items = sort_output_variables([var0, var1, var2, var3, var4])
		cvars = sort_condition_variables([cvar0,cvar1,cvar2])
		ctrl = sweep.SweepController([(('Res 2', res2),), (('Something', None),), (('Res 0', res0),),
				(('Res 1', res1), ('Res 3', res3))], vars, num_items,
				[('Meas res 0', meas_res0), ('Meas res 1', meas_res1)], [meas0, meas1],
				condition_resources, cvars)

		# Callback verification buffers.
		actual_values = []
		actual_measurement_values = []
		actual_writes = []
		actual_reads = []
		closed = [0]

		# Callbacks.
		def data_callback(cur_time, values, measurement_values):
			actual_values.append(values)
			actual_measurement_values.append(measurement_values)
		ctrl.data_callback = data_callback

		def close_callback():
			closed[0] += 1
		ctrl.close_callback = close_callback

		def write_callback(pos, i, value):
			actual_writes.append((pos, i, value))
		ctrl.write_callback = write_callback

		def read_callback(i, value):
			actual_reads.append((i, value))
		ctrl.read_callback = read_callback

		# Let it run.
		start_time = time()
		ctrl.run()
		elapsed_time = time() - start_time

		expected_time = num_items * dwell_time.value
		assert expected_time < elapsed_time, 'Took {0} s, expected at least {1} s.'.format(elapsed_time, expected_time)

		expected_res1 = [1.0, 2.0, 3.0, 4.0]
		expected_res2 = [-1.0, 0.0, 1.0, 2.0]

		expected_inner_writes = list(flatten(((3, 0, x), (3, 1, x - 2.0)) for x in [1.0, 2.0, 3.0, 4.0]))
		expected_writes = [(0, 0, 1.23), (1, 0, -10.0)] + list(flatten([(2, 0, x)] + expected_inner_writes
				for x in [Quantity(x, 'cm-1') for x in [-1.0, -2.0]]))

		eq_(res_bufs, [
			[Quantity(x, 'cm-1') for x in [0.0, -1.0, -1.0, -2.0, -2.0, 0.0]],
			[-1.0, 0.0, 1.0] + expected_res1 + [4.0, 2.5, 1.0] + expected_res1 + [4.0, 1.5, -1.0],
			[1.23],
			[-9.0, -1.0] + expected_res2 + expected_res2 + [2.0, -9.0],
		])
		
		eq_(measurement_counts, [24, -24])
		
	
		# Construct predicted actual values. 
		expected_actual_values = []
		for x in [Quantity(x, 'cm-1') for x in [-1.0, -2.0]]:
			for y in [1.0, 2.0, 3.0, 4.0]:
				
				# We append twice since the 0th order condition will create an extra measurement
				# for every non_conditionally based measurement
				expected_actual_values.append((1.23, -10.0, x, y, y - 2.0))
				expected_actual_values.append((1.23, -10.0, x, y, y - 2.0))
				
				# If were at the end of order 1, we append 4 more times to have a total of 6
				# This is because in the condition checking stage, we require the 0th order condition
				# and the 1st order conditions to all be true. So, cycling through entries in [0,1]
				# and [0,1,2], it will take a total of 6 condition checks to get 1 in [0,1], and 2 in
				# [0,1,2].
				if y == 4:
					expected_actual_values.append((1.23, -10.0, x, y, y - 2.0))
					expected_actual_values.append((1.23, -10.0, x, y, y - 2.0))
					expected_actual_values.append((1.23, -10.0, x, y, y - 2.0))
					expected_actual_values.append((1.23, -10.0, x, y, y - 2.0))
				

		eq_(actual_values, expected_actual_values)

		eq_(actual_measurement_values, [(x, -x) for x in xrange(1, 25)])
		eq_(actual_writes, expected_writes)
		eq_(actual_reads, list(flatten(((0, x), (1, -x)) for x in xrange(1, 25))))
		eq_(closed, [1])
	def testProper(self):
		"""
		Testing everything that there is to test along the happy path:
			nested and parallel variables
			measurements
			dwell time
		"""

		res_bufs = [[], [], [], []]
		measurement_counts = [0] * 2

		def setter(i, value):
			res_bufs[i].append(value)

		def getter(i):
			measurement_counts[i] += (-1) ** i

			return measurement_counts[i]

		dwell_time = Quantity(50, 'ms')

		# Output.
		res0 = Resource(setter=partial(setter, 0))
		res0.units = 'cm-1'
		res1 = Resource(setter=partial(setter, 1))
		res2 = Resource(setter=partial(setter, 2))
		res3 = Resource(setter=partial(setter, 3))

		var0 = OutputVariable(name='Var 0', order=2, enabled=True, const=0.0)
		var0.config = LinSpaceConfig(-1.0, -2.0, 2)
		var0.smooth_steps = 2
		var0.smooth_from, var0.smooth_to, var0.smooth_transition = [True] * 3
		var0.type = 'quantity'
		var0.units = 'cm-1'

		var1 = OutputVariable(name='Var 1', order=1, enabled=True, const=-1.0)
		var1.config = LinSpaceConfig(1.0, 4.0, 4)
		var1.smooth_steps = 3
		var1.smooth_from, var1.smooth_to, var1.smooth_transition = [True] * 3

		var2 = OutputVariable(name='Var 2', order=1, enabled=True, const=1.23, use_const=True)

		var3 = OutputVariable(name='Var 3', order=1, enabled=True, const=-9.0, wait=str(dwell_time))
		var3.config = LinSpaceConfig(-1.0, 2.0, 4)
		var3.smooth_steps = 2
		var3.smooth_from, var3.smooth_to, var3.smooth_transition = True, True, False

		var4 = OutputVariable(name='Var 4', order=3, enabled=True, const=-20.0)
		var4.config = LinSpaceConfig(-10.0, 20, 1)
		var4.smooth_steps = 2
		var4.smooth_from = True

		# Input.
		meas_res0 = Resource(getter=partial(getter, 0))
		meas_res1 = Resource(getter=partial(getter, 1))

		meas0 = InputVariable(name='Meas 0')
		meas1 = InputVariable(name='Meas 1')

		vars, num_items = sort_output_variables([var0, var1, var2, var3, var4])
		ctrl = sweep.SweepController([(('Res 2', res2),), (('Something', None),), (('Res 0', res0),),
				(('Res 1', res1), ('Res 3', res3))], vars, num_items,
				[('Meas res 0', meas_res0), ('Meas res 1', meas_res1)], [meas0, meas1])

		# Callback verification buffers.
		actual_values = []
		actual_measurement_values = []
		actual_writes = []
		actual_reads = []
		closed = [0]

		# Callbacks.
		def data_callback(cur_time, values, measurement_values):
			actual_values.append(values)
			actual_measurement_values.append(measurement_values)
		ctrl.data_callback = data_callback

		def close_callback():
			closed[0] += 1
		ctrl.close_callback = close_callback

		def write_callback(pos, i, value):
			actual_writes.append((pos, i, value))
		ctrl.write_callback = write_callback

		def read_callback(i, value):
			actual_reads.append((i, value))
		ctrl.read_callback = read_callback

		# Let it run.
		start_time = time()
		ctrl.run()
		elapsed_time = time() - start_time

		expected_time = num_items * dwell_time.value
		assert expected_time < elapsed_time, 'Took {0} s, expected at least {1} s.'.format(elapsed_time, expected_time)

		expected_res1 = [1.0, 2.0, 3.0, 4.0]
		expected_res2 = [-1.0, 0.0, 1.0, 2.0]

		expected_inner_writes = list(flatten(((3, 0, x), (3, 1, x - 2.0)) for x in [1.0, 2.0, 3.0, 4.0]))
		expected_writes = [(0, 0, 1.23), (1, 0, -10.0)] + list(flatten([(2, 0, x)] + expected_inner_writes
				for x in [Quantity(x, 'cm-1') for x in [-1.0, -2.0]]))

		eq_(res_bufs, [
			[Quantity(x, 'cm-1') for x in [0.0, -1.0, -1.0, -2.0, -2.0, 0.0]],
			[-1.0, 0.0, 1.0] + expected_res1 + [4.0, 2.5, 1.0] + expected_res1 + [4.0, 1.5, -1.0],
			[1.23],
			[-9.0, -1.0] + expected_res2 + expected_res2 + [2.0, -9.0],
		])
		eq_(measurement_counts, [8, -8])
		eq_(actual_values, [(1.23, -10.0, x, y, y - 2.0)
				for x in [Quantity(x, 'cm-1') for x in [-1.0, -2.0]]
				for y in [1.0, 2.0, 3.0, 4.0]])
		eq_(actual_measurement_values, [(x, -x) for x in xrange(1, 9)])
		eq_(actual_writes, expected_writes)
		eq_(actual_reads, list(flatten(((0, x), (1, -x)) for x in xrange(1, 9))))
		eq_(closed, [1])
	def testEvaluateCondition(self):
		"""
		Test if evaluating conditions works properly
		for different combinations of types.
		"""
		# Some variables to use for tests.
		
		res_bufs = [[], [], [], []]

		def setter(i, value):
			res_bufs[i].append(value)
			
		def getter(i):
			return res_bufs[i][0]
			
			
		a = Quantity('5 T')
		b = Quantity('50 kG')
		c = 'on'

		res0 = Resource(getter=partial(getter,0), setter=partial(setter, 0))
		res0.units = 'T'
		res1 = Resource(getter=partial(getter,1), setter=partial(setter, 1))
		res1.units = 'kG'
		res2 = Resource(getter=partial(getter,2), setter=partial(setter, 2))
		res2.allowed_values = ['on','off']
		
		res0.value = a
		res1.value = b
		res2.value = c

		# Check 2 quantities of equivalent units.
		c1 = variables.Condition('quantity','quantity',a,'==',b)
		eq_(c1.evaluate(), True)
		
		# Check a resource against a quantity.
		c2 = variables.Condition('resource','quantity',res0,'==',a)
		eq_(c2.evaluate(), True)
		
		# Check a resource with a resource.
		c3 = variables.Condition('resource','resource',res0,'==',res1)
		eq_(c3.evaluate(), True)
		
		# Check a resource that has an allowed value with a string.
		c4 = variables.Condition('resource','string',res2,'==',c)
		eq_(c4.evaluate(), True)
		
		# Test evaluating resource names.
		resources = [('res0',res0),('res1',res1),('res2',res2)]
		c3 = variables.Condition('resource name','resource name','res0','==','res1')
		eq_(c3.evaluate(resources), True)
		
		# Check some things that should mess up.
		
		## string instead of quantity.
		try:
			c5 = variables.Condition('resource','string',res0,'==','5 T')
			eq_(c5.evaluate(), True)
		except TypeError:
			pass
		else:
			assert False, 'Expected TypeError.'
		
		## not matching units.
		try:
			c6 = variables.Condition('quantity','quantity',Quantity('5 A'),'==',Quantity('5 T'))
			eq_(c6.evaluate(), True)
		except IncompatibleDimensions:
			pass
		else:
			assert False, 'Expected IncompatibleDimensions error.'