def add_lines_after_overlapping():
	"""The lines after an add are shifted down, even when the adds are overlapping."""

	staticdiffmodel = _make_static_diffmodel()
	editable = EditableDiffModel( staticdiffmodel )

	editable.add_lines( 2, directions.LEFT, ["new line 2a", "new line 2c"] )
	editable.add_lines( 3, directions.LEFT, ["new line 2b"] )

	# Get some lines after the add
	lines = editable.get_lines( 6, 8 )

	assert( len( lines ) == 2 )

	ln = lines[0]
	assert_strings_equal( ln.left, "line 4 here" )
	assert_strings_equal( ln.right, "line 4 here" )
	assert( ln.status == difflinetypes.IDENTICAL )
	assert( ln.left_edited == False )
	assert( ln.right_edited == False )
	assert( ln == editable.get_line( 6 ) ) # Sanity for get_line

	ln = lines[1]
	assert_strings_equal( ln.left, "line 5 here" )
	assert_strings_equal( ln.right, "line 5 here different" )
	assert( ln.status == difflinetypes.DIFFERENT )
	assert( ln.left_edited == False )
	assert( ln.right_edited == False )
	assert( ln == editable.get_line( 7 ) ) # Sanity for get_line
def add_lines_spanning():
	"""If an add overlaps the entire region we asking for,
	we still calculate the right answer."""

	staticdiffmodel = _make_static_diffmodel()
	editable = EditableDiffModel( staticdiffmodel )

	editable.add_lines( 1, directions.RIGHT,
		[
		"new line 1a",
		"new line 1b",
		"new line 1c",
		"new line 1d",
		] )

	# Get some lines containing the add
	lines = editable.get_lines( 2, 4 )
	assert( len( lines ) == 2 )

	ln = lines[0]
	assert_strings_equal( ln.left, None )
	assert_strings_equal( ln.right, "new line 1b" )
	assert( ln.status == difflinetypes.DIFFERENT )
	assert( ln.left_edited == False )
	assert( ln.right_edited == True )
	assert( ln == editable.get_line( 2 ) ) # Sanity for get_line

	ln = lines[1]
	assert_strings_equal( ln.left, None )
	assert_strings_equal( ln.right, "new line 1c" )
	assert( ln.status == difflinetypes.DIFFERENT )
	assert( ln.left_edited == False )
	assert( ln.right_edited == True )
	assert( ln == editable.get_line( 3 ) ) # Sanity for get_line
def add_then_delete():
	"""If we add some lines and then delete some of them later we get
	the right result."""

	staticdiffmodel = _make_static_diffmodel()
	editable = EditableDiffModel( staticdiffmodel )

	editable.add_lines( 1, directions.RIGHT,
		[ "Added line 1a", "Added line 1b", "Added line 1c" ] )

	editable.delete_lines( 2, 2, directions.RIGHT )

	# Get some lines containing the add
	lines = editable.get_lines( 0, 5 )
	assert( len( lines ) == 5 )

	ln = lines[0]
	assert_strings_equal( ln.left, "line 1 here" )
	assert_strings_equal( ln.right, "line 1 here" )

	ln = lines[1]
	assert_strings_equal( ln.left, None )
	assert_strings_equal( ln.right, "Added line 1a" )

	ln = lines[2]
	assert_strings_equal( ln.left, None )
	assert_strings_equal( ln.right, None )

	ln = lines[3]
	assert_strings_equal( ln.left, None )
	assert_strings_equal( ln.right, "Added line 1c" )

	ln = lines[4]
	assert_strings_equal( ln.left, "line 2 here" )
	assert_strings_equal( ln.right, "line 2 here" )
def add_then_edit():
	"""If we add a line and then edit it later we get the right result."""

	staticdiffmodel = _make_static_diffmodel()
	editable = EditableDiffModel( staticdiffmodel )

	editable.add_lines( 1, directions.RIGHT,
		[ "Added line 1a", ] )

	editable.edit_lines( 1, 1, directions.LEFT,
		[ "Edited line 1b" ] )

	# Get some lines containing the add
	lines = editable.get_lines( 0, 3 )
	assert( len( lines ) == 3 )

	ln = lines[0]
	assert_strings_equal( ln.left, "line 1 here" )
	assert_strings_equal( ln.right, "line 1 here" )

	ln = lines[1]
	assert_strings_equal( ln.left, "Edited line 1b" )
	assert_strings_equal( ln.right, "Added line 1a" )

	ln = lines[2]
	assert_strings_equal( ln.left, "line 2 here" )
	assert_strings_equal( ln.right, "line 2 here" )
def add_lines_containing():
	"""The lines containing an add are calculated correctly."""

	staticdiffmodel = _make_static_diffmodel()
	editable = EditableDiffModel( staticdiffmodel )

	editable.add_lines( 3, directions.LEFT, ["new line 3a", "new line 3b"] )

	# Get some lines containing the add
	lines = editable.get_lines( 1, 6 )
	assert( len( lines ) == 5 )

	ln = lines[0]
	assert_strings_equal( ln.left, "line 2 here" )
	assert_strings_equal( ln.right, "line 2 here" )
	assert( ln.status == difflinetypes.IDENTICAL )
	assert( ln.left_edited == False )
	assert( ln.right_edited == False )
	assert( ln == editable.get_line( 1 ) ) # Sanity for get_line

	ln = lines[1]
	assert_strings_equal( ln.left, "line 3 here" )
	assert_strings_equal( ln.right, "line 3 here" )
	assert( ln.status == difflinetypes.IDENTICAL )
	assert( ln.left_edited == False )
	assert( ln.right_edited == False )
	assert( ln == editable.get_line( 2 ) ) # Sanity for get_line

	ln = lines[2]
	assert_strings_equal( ln.left, "new line 3a" )
	assert_strings_equal( ln.right, None )
	assert( ln.status == difflinetypes.DIFFERENT )
	assert( ln.left_edited == True )
	assert( ln.right_edited == False )
	assert( ln == editable.get_line( 3 ) ) # Sanity for get_line

	ln = lines[3]
	assert_strings_equal( ln.left, "new line 3b" )
	assert_strings_equal( ln.right, None )
	assert( ln.status == difflinetypes.DIFFERENT )
	assert( ln.left_edited == True )
	assert( ln.right_edited == False )
	assert( ln == editable.get_line( 4 ) ) # Sanity for get_line

	ln = lines[4]
	assert_strings_equal( ln.left, "line 4 here" )
	assert_strings_equal( ln.right, "line 4 here" )
	assert( ln.status == difflinetypes.IDENTICAL )
	assert( ln.left_edited == False )
	assert( ln.right_edited == False )
	assert( ln == editable.get_line( 5 ) ) # Sanity for get_line
def add_lines_write_to_file():
	fakefile = FakeFile()

	staticdiffmodel = _make_static_diffmodel()
	old_static_lines = list( ln.clone() for ln in staticdiffmodel.get_lines() )

	editable = EditableDiffModel( staticdiffmodel )

	# Make several overlapping changes, including a deletion
	editable.edit_lines( 0, 2, directions.RIGHT,
		( "edited 1a", "edited 2a", "edited 3a" ) )

	editable.add_lines( 1, directions.LEFT,
		[ "Unimportant 1", "Unimportant 2" ] )

	editable.edit_lines( 3, 5, directions.RIGHT,
		( "edited 2b", "edited 3b", "edited 4b" ) )

	editable.add_lines( 3, directions.RIGHT,
		[ "Added 1", "Added 2" ] )

	editable.delete_lines( 3, 3, directions.RIGHT )

	editable.edit_lines( 6, 8, directions.RIGHT,
		( "edited 3c", "edited 4c", "edited 5c" ) )

	editable.write_to_file( fakefile, directions.RIGHT )

	assert_strings_equal( fakefile.txt,
		  "edited 1a\n"
		+ "Added 2\n"
		+ "edited 2b\n"
		+ "edited 3c\n"
		+ "edited 4c\n"
		+ "edited 5c\n"
		+ "line 6 here\n"
		+ "line 7 here\n"
		+ "line 8 here\n"
		+ "line 9 here\n"
		+ "line 10 here\n"
		)

	assert_lines_lists_equal( old_static_lines, staticdiffmodel.get_lines() )
def add_lines_overlapping_left():
	"""If an add overlaps the region we are asking for on the left,
	we still calculate the right answer."""

	staticdiffmodel = _make_static_diffmodel()
	editable = EditableDiffModel( staticdiffmodel )

	editable.add_lines( 3, directions.RIGHT,
		[
		"new line 3a",
		"new line 3b",
		"new line 3c",
		"new line 3d",
		] )

	# Get some lines containing the add
	lines = editable.get_lines( 5, 8 )
	assert( len( lines ) == 3 )

	ln = lines[0]
	assert_strings_equal( ln.left, None )
	assert_strings_equal( ln.right, "new line 3c" )
	assert( ln.status == difflinetypes.DIFFERENT )
	assert( ln.left_edited == False )
	assert( ln.right_edited == True )
	assert( ln == editable.get_line( 5 ) ) # Sanity for get_line

	ln = editable.get_line( 6 )
	assert_strings_equal( ln.left, None )
	assert_strings_equal( ln.right, "new line 3d" )
	assert( ln.status == difflinetypes.DIFFERENT )
	assert( ln.left_edited == False )
	assert( ln.right_edited == True )
	assert( ln == lines[1] ) # Sanity - get_lines gives same answer as get_line

	ln = lines[2]
	assert_strings_equal( ln.left, "line 4 here" )
	assert_strings_equal( ln.right, "line 4 here" )
	assert( ln.status == difflinetypes.IDENTICAL )
	assert( ln.left_edited == False )
	assert( ln.right_edited == False )
	assert( ln == editable.get_line( 7 ) ) # Sanity for get_line
def add_at_beginning():
	staticdiffmodel = _make_static_diffmodel()
	old_static_lines = list( ln.clone() for ln in staticdiffmodel.get_lines() )

	editable = EditableDiffModel( staticdiffmodel )

	# Make an add at the beginning of the file
	editable.add_lines( 0, directions.RIGHT,
		( [ "Added 0a", "Added 0b"] ) )

	lines = editable.get_lines( 0, 3 )
	assert( len( lines ) == 3 )

	ln = lines[0]
	assert_strings_equal( ln.left, None )
	assert_strings_equal( ln.right, "Added 0a" )

	ln = lines[1]
	assert_strings_equal( ln.left, None )
	assert_strings_equal( ln.right, "Added 0b" )
def add_lines_before():
	"""The lines before an add are unaffected by it."""

	staticdiffmodel = _make_static_diffmodel()
	editable = EditableDiffModel( staticdiffmodel )

	editable.add_lines( 3, directions.LEFT, ["new line 3a", "new line 3b"] )
	editable.add_lines( 6, directions.LEFT, ["new line 4a", "new line 4b"] )

	# Get some lines before the add
	lines = editable.get_lines( 0, 3 )
	assert( len( lines ) == 3 )

	ln = lines[0]
	assert_strings_equal( ln.left, "line 1 here" )
	assert_strings_equal( ln.right, "line 1 here" )
	assert( ln.status == difflinetypes.IDENTICAL )
	assert( ln.left_edited == False )
	assert( ln.right_edited == False )
	assert( ln == editable.get_line( 0 ) ) # Sanity for get_line

	ln = lines[1]
	assert_strings_equal( ln.left, "line 2 here" )
	assert_strings_equal( ln.right, "line 2 here" )
	assert( ln.status == difflinetypes.IDENTICAL )
	assert( ln.left_edited == False )
	assert( ln.right_edited == False )
	assert( ln == editable.get_line( 1 ) ) # Sanity for get_line

	ln = lines[2]
	assert_strings_equal( ln.left, "line 3 here" )
	assert_strings_equal( ln.right, "line 3 here" )
	assert( ln.status == difflinetypes.IDENTICAL )
	assert( ln.left_edited == False )
	assert( ln.right_edited == False )
	assert( ln == editable.get_line( 2 ) ) # Sanity for get_line
def add_lines_get_num_lines():
	"""The number of lines is correctly reported when lines have been added."""

	staticdiffmodel = _make_static_diffmodel()
	editable = EditableDiffModel( staticdiffmodel )

	assert( editable.get_num_lines() == 10 )

	editable.add_lines( 3, directions.LEFT,
		["new line 3a", "new line 3b", "new line 3c"] )

	assert( editable.get_num_lines() == 13 )

	editable.add_lines( 6, directions.LEFT, ["new line 4a", "new line 4b"] )
	editable.add_lines( 4, directions.LEFT, ["new line 3ai", "new line 3aii"] )

	assert( editable.get_num_lines() == 17 )
def add_lines_ask_for_all():
	"""If we ask for all the lines after adding some, we get
	them correctly."""

	staticdiffmodel = _make_static_diffmodel()
	editable = EditableDiffModel( staticdiffmodel )

	editable.add_lines( 1, directions.RIGHT,
		[
		"new line 1a",
		"new line 1b",
		"new line 1c",
		"new line 1d",
		] )

	editable.add_lines( 3, directions.LEFT,
		[
		"new line 1bi",
		"new line 1bii",
		] )

	# Get some lines containing the add
	lines = editable.get_lines()
	assert( len( lines ) == 16 )

	ln = lines[0]
	assert_strings_equal( ln.left, "line 1 here" )
	assert_strings_equal( ln.right, "line 1 here" )

	ln = lines[1]
	assert_strings_equal( ln.left, None )
	assert_strings_equal( ln.right, "new line 1a" )
	assert( ln.status == difflinetypes.DIFFERENT )
	assert( ln.left_edited == False )
	assert( ln.right_edited == True )

	ln = lines[2]
	assert_strings_equal( ln.left, None )
	assert_strings_equal( ln.right, "new line 1b" )

	ln = lines[3]
	assert_strings_equal( ln.left, "new line 1bi" )
	assert_strings_equal( ln.right, None )
	assert( ln.status == difflinetypes.DIFFERENT )
	assert( ln.left_edited == True )
	assert( ln.right_edited == False )

	ln = lines[4]
	assert_strings_equal( ln.left, "new line 1bii" )
	assert_strings_equal( ln.right, None )

	ln = lines[5]
	assert_strings_equal( ln.left, None )
	assert_strings_equal( ln.right, "new line 1c" )
	assert( ln.status == difflinetypes.DIFFERENT )
	assert( ln.left_edited == False )
	assert( ln.right_edited == True )

	ln = lines[6]
	assert_strings_equal( ln.left, None )
	assert_strings_equal( ln.right, "new line 1d" )

	ln = lines[7]
	assert_strings_equal( ln.left, "line 2 here" )
	assert_strings_equal( ln.right, "line 2 here" )

	ln = lines[8]
	assert_strings_equal( ln.left, "line 3 here" )
	assert_strings_equal( ln.right, "line 3 here" )

	ln = lines[9]
	assert_strings_equal( ln.left, "line 4 here" )
	assert_strings_equal( ln.right, "line 4 here" )
def has_edit_affecting_side_after_save():

	staticdiffmodel = _make_static_diffmodel()
	editable = EditableDiffModel( staticdiffmodel )

	editable.edit_lines( 0, 2, directions.RIGHT,
		( "edited 1a", "edited 2a", "edited 3a" ) )

	editable.edit_lines( 0, 2, directions.LEFT,
		( "edited left 1a", "edited left 2a", "edited left 3a" ) )

	assert( editable.has_edit_affecting_side( directions.RIGHT ) )
	assert( editable.has_edit_affecting_side( directions.LEFT ) )

	lines = editable.get_lines( 0, 3 )
	assert( len( lines ) == 3 )

	ln = lines[0]
	assert_strings_equal( ln.left, "edited left 1a" )
	assert_strings_equal( ln.right, "edited 1a" )
	assert( ln.status == difflinetypes.DIFFERENT )
	assert( ln.left_edited == True )
	assert( ln.right_edited == True )

	editable.set_save_point( directions.LEFT )

	lines = editable.get_lines( 0, 3 )
	assert( len( lines ) == 3 )

	ln = lines[0]
	assert_strings_equal( ln.left, "edited left 1a" )
	assert_strings_equal( ln.right, "edited 1a" )
	assert( ln.status == difflinetypes.DIFFERENT )
	assert( ln.left_edited == False )
	assert( ln.right_edited == True )

	assert( editable.has_edit_affecting_side( directions.RIGHT ) )
	assert( not editable.has_edit_affecting_side( directions.LEFT ) )

	editable.edit_lines( 0, 2, directions.RIGHT,
		( "edited 1b", "edited 2b", "edited 3b" ) )

	editable.set_save_point( directions.RIGHT )

	assert( not editable.has_edit_affecting_side( directions.RIGHT ) )
	assert( not editable.has_edit_affecting_side( directions.LEFT ) )

	lines = editable.get_lines( 0, 3 )
	assert( len( lines ) == 3 )

	ln = lines[0]
	assert_strings_equal( ln.left, "edited left 1a" )
	assert_strings_equal( ln.right, "edited 1b" )
	assert( ln.status == difflinetypes.DIFFERENT )
	assert( ln.left_edited == False )
	assert( ln.right_edited == False )

	editable.add_lines( 3, directions.LEFT,
		[ "Added line 1", "Added line 1", "Added line 1" ] )

	assert( not editable.has_edit_affecting_side( directions.RIGHT ) )
	assert( editable.has_edit_affecting_side( directions.LEFT ) )

	editable.add_lines( 3, directions.RIGHT,
		[ "Added line 1", "Added line 1", "Added line 1" ] )

	assert( editable.has_edit_affecting_side( directions.RIGHT ) )
	assert( editable.has_edit_affecting_side( directions.LEFT ) )

	editable.set_save_point( directions.LEFT )

	assert( editable.has_edit_affecting_side( directions.RIGHT ) )
	assert( not editable.has_edit_affecting_side( directions.LEFT ) )

	editable.set_save_point( directions.RIGHT )

	assert( not editable.has_edit_affecting_side( directions.RIGHT ) )
	assert( not editable.has_edit_affecting_side( directions.LEFT ) )
def several_edits_and_adds():
	staticdiffmodel = _make_static_diffmodel()
	old_static_lines = list( ln.clone() for ln in staticdiffmodel.get_lines() )

	editable = EditableDiffModel( staticdiffmodel )

	# Make several overlapping changes
	editable.edit_lines( 0, 2, directions.RIGHT,
		( "edited 1a", "edited 2a", "edited 3a" ) )

	editable.add_lines( 1, directions.RIGHT,
		( [ "Added 1a+1", "Added 1a+4"] ) )

	editable.add_lines( 2, directions.LEFT,
		( [ "Added 1a+2", "Added 1a+3"] ) )

	editable.edit_lines( 3, 5, directions.RIGHT,
		( "edited 1a+3e", "edited 1a+4e", "edited 2b" ) )

	editable.add_lines( 3, directions.RIGHT,
		( [ "Added 2a+2a" ] ) )

	editable.edit_lines( 7, 9, directions.RIGHT,
		( "edited 3c", "edited 4c", "edited 5c" ) )

	lines = editable.get_lines( 0, 11 )
	assert( len( lines ) == 11 )

	ln = lines[0]
	assert_strings_equal( ln.left, "line 1 here" )
	assert_strings_equal( ln.right, "edited 1a" )
	assert( ln.status == difflinetypes.DIFFERENT )
	assert( ln.left_edited == False )
	assert( ln.right_edited == True )

	ln = lines[1]
	assert_strings_equal( ln.left, None )
	assert_strings_equal( ln.right, "Added 1a+1" )
	assert( ln.status == difflinetypes.DIFFERENT )
	assert( ln.left_edited == False )
	assert( ln.right_edited == True )

	ln = lines[2]
	assert_strings_equal( ln.left, "Added 1a+2" )
	assert_strings_equal( ln.right, None )
	assert( ln.status == difflinetypes.DIFFERENT )
	assert( ln.left_edited == True )
	assert( ln.right_edited == False )

	ln = lines[3]
	assert_strings_equal( ln.left, None )
	assert_strings_equal( ln.right, "Added 2a+2a" )
	assert( ln.status == difflinetypes.DIFFERENT )
	assert( ln.left_edited == False )
	assert( ln.right_edited == True )

	ln = lines[4]
	assert_strings_equal( ln.left, "Added 1a+3" )
	assert_strings_equal( ln.right, "edited 1a+3e" )
	assert( ln.status == difflinetypes.DIFFERENT )
	assert( ln.left_edited == True )
	assert( ln.right_edited == True )

	ln = lines[5]
	assert_strings_equal( ln.left, None )
	assert_strings_equal( ln.right, "edited 1a+4e" ) # Was "Added 1a+4"
	assert( ln.status == difflinetypes.DIFFERENT )
	assert( ln.left_edited == False )
	assert( ln.right_edited == True )

	ln = lines[6]
	assert_strings_equal( ln.left, "line 2 here" )
	assert_strings_equal( ln.right, "edited 2b" )
	assert( ln.status == difflinetypes.DIFFERENT )
	assert( ln.left_edited == False )
	assert( ln.right_edited == True )

	ln = lines[7]
	assert_strings_equal( ln.left, "line 3 here" )
	assert_strings_equal( ln.right, "edited 3c" )
	assert( ln.status == difflinetypes.DIFFERENT )
	assert( ln.left_edited == False )
	assert( ln.right_edited == True )

	ln = lines[8]
	assert_strings_equal( ln.left, "line 4 here" )
	assert_strings_equal( ln.right, "edited 4c" )
	assert( ln.status == difflinetypes.DIFFERENT )
	assert( ln.left_edited == False )
	assert( ln.right_edited == True )

	ln = lines[9]
	assert_strings_equal( ln.left, "line 5 here" )
	assert_strings_equal( ln.right, "edited 5c" )
	assert( ln.status == difflinetypes.DIFFERENT )
	assert( ln.left_edited == False )
	assert( ln.right_edited == True )

	ln = lines[10]
	assert_strings_equal( ln.left, "line 6 here" )
	assert_strings_equal( ln.right, "line 6 here" )
	assert( ln.status == difflinetypes.IDENTICAL )
	assert( ln.left_edited == False )
	assert( ln.right_edited == False )

	assert_lines_lists_equal( old_static_lines, staticdiffmodel.get_lines() )
def add_inside_another_add():
	"""If an add lands inside another add,
	we still calculate the right answer."""

	staticdiffmodel = _make_static_diffmodel()
	editable = EditableDiffModel( staticdiffmodel )

	editable.add_lines( 1, directions.RIGHT,
		[
		"new line 1a",
		"new line 1b",
		"new line 1c",
		"new line 1d",
		] )

	editable.add_lines( 3, directions.LEFT,
		[
		"new line 1bi",
		"new line 1bii",
		] )

	# Get some lines containing the add
	lines = editable.get_lines( 0 , 8 )
	assert( len( lines ) == 8 )

	ln = lines[0]
	assert_strings_equal( ln.left, "line 1 here" )
	assert_strings_equal( ln.right, "line 1 here" )
	assert( ln == editable.get_line( 0 ) ) # Sanity for get_line

	ln = lines[1]
	assert_strings_equal( ln.left, None )
	assert_strings_equal( ln.right, "new line 1a" )
	assert( ln.status == difflinetypes.DIFFERENT )
	assert( ln.left_edited == False )
	assert( ln.right_edited == True )
	assert( ln == editable.get_line( 1 ) ) # Sanity for get_line

	ln = lines[2]
	assert_strings_equal( ln.left, None )
	assert_strings_equal( ln.right, "new line 1b" )
	assert( ln == editable.get_line( 2 ) ) # Sanity for get_line

	ln = lines[3]
	assert_strings_equal( ln.left, "new line 1bi" )
	assert_strings_equal( ln.right, None )
	assert( ln.status == difflinetypes.DIFFERENT )
	assert( ln.left_edited == True )
	assert( ln.right_edited == False )
	assert( ln == editable.get_line( 3 ) ) # Sanity for get_line

	ln = lines[4]
	assert_strings_equal( ln.left, "new line 1bii" )
	assert_strings_equal( ln.right, None )
	assert( ln == editable.get_line( 4 ) ) # Sanity for get_line

	ln = lines[5]
	assert_strings_equal( ln.left, None )
	assert_strings_equal( ln.right, "new line 1c" )
	assert( ln.status == difflinetypes.DIFFERENT )
	assert( ln.left_edited == False )
	assert( ln.right_edited == True )
	assert( ln == editable.get_line( 5 ) ) # Sanity for get_line

	ln = lines[6]
	assert_strings_equal( ln.left, None )
	assert_strings_equal( ln.right, "new line 1d" )
	assert( ln == editable.get_line( 6 ) ) # Sanity for get_line

	ln = lines[7]
	assert_strings_equal( ln.left, "line 2 here" )
	assert_strings_equal( ln.right, "line 2 here" )
	assert( ln == editable.get_line( 7 ) ) # Sanity for get_line