~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_transform.py

Tests for DiskTreeTransform.finalize issues when create_file is interrupted

Show diffs side-by-side

added added

removed removed

Lines of Context:
2464
2464
        self.assertPathExists('a/b')
2465
2465
 
2466
2466
 
 
2467
class TestCleanup(tests.TestCaseWithTransport):
 
2468
 
 
2469
    def _override_globals_in_method(self, instance, method_name, globals):
 
2470
        """Replace method on instance with one with updated globals"""
 
2471
        import types
 
2472
        func = getattr(instance, method_name).im_func
 
2473
        new_globals = dict(func.func_globals)
 
2474
        new_globals.update(globals)
 
2475
        new_func = types.FunctionType(func.func_code, new_globals,
 
2476
            func.func_name, func.func_defaults)
 
2477
        setattr(instance, method_name,
 
2478
            types.MethodType(new_func, instance, instance.__class__))
 
2479
        self.addCleanup(delattr, instance, method_name)
 
2480
 
 
2481
    @staticmethod
 
2482
    def _fake_open_raises_before(name, mode):
 
2483
        """Like open() but raises before doing anything"""
 
2484
        raise RuntimeError
 
2485
 
 
2486
    @staticmethod
 
2487
    def _fake_open_raises_after(name, mode):
 
2488
        """Like open() but raises after creating file without returning"""
 
2489
        open(name, mode).close()
 
2490
        raise RuntimeError
 
2491
 
 
2492
    def create_transform_and_root_trans_id(self):
 
2493
        """Setup a transform creating a file in limbo"""
 
2494
        tree = self.make_branch_and_tree('.')
 
2495
        tt = TreeTransform(tree)
 
2496
        return tt, tt.create_path("a", tt.root)
 
2497
 
 
2498
    def create_transform_and_subdir_trans_id(self):
 
2499
        """Setup a transform creating a directory containing a file in limbo"""
 
2500
        tree = self.make_branch_and_tree('.')
 
2501
        tt = TreeTransform(tree)
 
2502
        d_trans_id = tt.create_path("d", tt.root)
 
2503
        tt.create_directory(d_trans_id)
 
2504
        f_trans_id = tt.create_path("a", d_trans_id)
 
2505
        tt.adjust_path("a", d_trans_id, f_trans_id)
 
2506
        return tt, f_trans_id
 
2507
 
 
2508
    def test_root_create_file_open_raises_before_creation(self):
 
2509
        tt, trans_id = self.create_transform_and_root_trans_id()
 
2510
        self._override_globals_in_method(tt, "create_file",
 
2511
            {"open": self._fake_open_raises_before})
 
2512
        self.assertRaises(RuntimeError, tt.create_file, ["contents"], trans_id)
 
2513
        path = tt._limbo_name(trans_id)
 
2514
        self.assertPathDoesNotExist(path)
 
2515
        tt.finalize()
 
2516
        self.assertPathDoesNotExist(tt._limbodir)
 
2517
 
 
2518
    def test_root_create_file_open_raises_after_creation(self):
 
2519
        tt, trans_id = self.create_transform_and_root_trans_id()
 
2520
        self._override_globals_in_method(tt, "create_file",
 
2521
            {"open": self._fake_open_raises_after})
 
2522
        self.assertRaises(RuntimeError, tt.create_file, ["contents"], trans_id)
 
2523
        path = tt._limbo_name(trans_id)
 
2524
        self.assertPathExists(path)
 
2525
        # GZ 2011-05-17: Why raise ImmortalLimbo, masking the earlier error,
 
2526
        #                rather than just emitting a warning or similar?
 
2527
        self.assertRaises(errors.ImmortalLimbo, tt.finalize)
 
2528
        self.assertPathExists(path)
 
2529
        self.assertPathExists(tt._limbodir)
 
2530
 
 
2531
    def test_subdir_create_file_open_raises_before_creation(self):
 
2532
        tt, trans_id = self.create_transform_and_subdir_trans_id()
 
2533
        self._override_globals_in_method(tt, "create_file",
 
2534
            {"open": self._fake_open_raises_before})
 
2535
        self.assertRaises(RuntimeError, tt.create_file, ["contents"], trans_id)
 
2536
        path = tt._limbo_name(trans_id)
 
2537
        self.assertPathDoesNotExist(path)
 
2538
        tt.finalize()
 
2539
        self.assertPathDoesNotExist(tt._limbodir)
 
2540
 
 
2541
    def test_subdir_create_file_open_raises_after_creation(self):
 
2542
        tt, trans_id = self.create_transform_and_subdir_trans_id()
 
2543
        self._override_globals_in_method(tt, "create_file",
 
2544
            {"open": self._fake_open_raises_after})
 
2545
        self.assertRaises(RuntimeError, tt.create_file, ["contents"], trans_id)
 
2546
        path = tt._limbo_name(trans_id)
 
2547
        self.assertPathExists(path)
 
2548
        tt.finalize()
 
2549
        self.assertPathDoesNotExist(path)
 
2550
        self.assertPathDoesNotExist(tt._limbodir)
 
2551
 
 
2552
 
2467
2553
class TestTransformMissingParent(tests.TestCaseWithTransport):
2468
2554
 
2469
2555
    def make_tt_with_versioned_dir(self):