tests/test-dirstate-status-write-race.t
branchstable
changeset 50215 ae61851e6fe2
child 50216 02bf2f94a04c
equal deleted inserted replaced
50214:8e0d823ef182 50215:ae61851e6fe2
       
     1 =====================================================================
       
     2 Check potential race conditions between a status and other operations
       
     3 =====================================================================
       
     4 
       
     5 The `hg status` command can run without the wlock, however it might end up
       
     6 having to update the on-disk dirstate files, for example to mark ambiguous
       
     7 files as clean, or to update directory caches information with dirstate-v2.
       
     8 
       
     9 
       
    10 If another process updates the dirstate in the meantime we might run into
       
    11 trouble. Especially, commands doing semantic changes like `hg add` or
       
    12  `hg commit` should not see their update erased by a concurrent status.
       
    13 
       
    14 Unlike commands like `add` or `commit`, `status` only writes the dirstate
       
    15 to update caches, no actual information is lost if we fail to write to disk.
       
    16 
       
    17 
       
    18 This test file is meant to test various cases where such parallel operations
       
    19 between a status with reasons to update the dirstate and another semantic
       
    20 changes happen.
       
    21 
       
    22 
       
    23 Setup
       
    24 =====
       
    25 
       
    26   $ directories="dir dir/nested dir2"
       
    27   $ first_files="dir/nested/a dir/b dir/c dir/d dir2/e f"
       
    28   $ second_files="g dir/nested/h dir/i dir/j dir2/k dir2/l dir/nested/m"
       
    29   $ extra_files="dir/n dir/o p q"
       
    30 
       
    31   $ hg init reference-repo
       
    32   $ cd reference-repo
       
    33   $ mkdir -p dir/nested dir2
       
    34   $ touch -t 200001010000 $first_files $directories
       
    35   $ hg commit -Aqm "recreate a bunch of files to facilitate dirstate-v2 append"
       
    36   $ touch -t 200001010010 $second_files $directories
       
    37   $ hg commit -Aqm "more files to have two commits"
       
    38   $ hg log -G -v
       
    39   @  changeset:   1:c349430a1631
       
    40   |  tag:         tip
       
    41   |  user:        test
       
    42   |  date:        Thu Jan 01 00:00:00 1970 +0000
       
    43   |  files:       dir/i dir/j dir/nested/h dir/nested/m dir2/k dir2/l g
       
    44   |  description:
       
    45   |  more files to have two commits
       
    46   |
       
    47   |
       
    48   o  changeset:   0:4f23db756b09
       
    49      user:        test
       
    50      date:        Thu Jan 01 00:00:00 1970 +0000
       
    51      files:       dir/b dir/c dir/d dir/nested/a dir2/e f
       
    52      description:
       
    53      recreate a bunch of files to facilitate dirstate-v2 append
       
    54   
       
    55   
       
    56   $ hg manifest
       
    57   dir/b
       
    58   dir/c
       
    59   dir/d
       
    60   dir/i
       
    61   dir/j
       
    62   dir/nested/a
       
    63   dir/nested/h
       
    64   dir/nested/m
       
    65   dir2/e
       
    66   dir2/k
       
    67   dir2/l
       
    68   f
       
    69   g
       
    70 
       
    71 Add some unknown files and refresh the dirstate
       
    72 
       
    73   $ touch -t 200001010020 $extra_files
       
    74   $ hg add dir/o
       
    75   $ hg remove dir/nested/m
       
    76 
       
    77   $ hg st
       
    78   A dir/o
       
    79   R dir/nested/m
       
    80   ? dir/n
       
    81   ? p
       
    82   ? q
       
    83   $ hg debugstate
       
    84   n 644          0 2000-01-01 00:00:00 dir/b
       
    85   n 644          0 2000-01-01 00:00:00 dir/c
       
    86   n 644          0 2000-01-01 00:00:00 dir/d
       
    87   n 644          0 2000-01-01 00:10:00 dir/i
       
    88   n 644          0 2000-01-01 00:10:00 dir/j
       
    89   n 644          0 2000-01-01 00:00:00 dir/nested/a
       
    90   n 644          0 2000-01-01 00:10:00 dir/nested/h
       
    91   r ?????????????????????????????????? dir/nested/m (glob)
       
    92   a ?????????????????????????????????? dir/o (glob)
       
    93   n 644          0 2000-01-01 00:00:00 dir2/e
       
    94   n 644          0 2000-01-01 00:10:00 dir2/k
       
    95   n 644          0 2000-01-01 00:10:00 dir2/l
       
    96   n 644          0 2000-01-01 00:00:00 f
       
    97   n 644          0 2000-01-01 00:10:00 g
       
    98   $ hg debugstate > ../reference
       
    99   $ cd ..
       
   100 
       
   101 Explain / verify the test principles
       
   102 ------------------------------------
       
   103 
       
   104 First, we can properly copy the reference
       
   105 
       
   106   $ cp -a reference-repo sanity-check
       
   107   $ cd sanity-check
       
   108   $ hg debugstate
       
   109   n 644          0 2000-01-01 00:00:00 dir/b
       
   110   n 644          0 2000-01-01 00:00:00 dir/c
       
   111   n 644          0 2000-01-01 00:00:00 dir/d
       
   112   n 644          0 2000-01-01 00:10:00 dir/i
       
   113   n 644          0 2000-01-01 00:10:00 dir/j
       
   114   n 644          0 2000-01-01 00:00:00 dir/nested/a
       
   115   n 644          0 2000-01-01 00:10:00 dir/nested/h
       
   116   r ?????????????????????????????????? dir/nested/m (glob)
       
   117   a ?????????????????????????????????? dir/o (glob)
       
   118   n 644          0 2000-01-01 00:00:00 dir2/e
       
   119   n 644          0 2000-01-01 00:10:00 dir2/k
       
   120   n 644          0 2000-01-01 00:10:00 dir2/l
       
   121   n 644          0 2000-01-01 00:00:00 f
       
   122   n 644          0 2000-01-01 00:10:00 g
       
   123   $ hg debugstate > ../post-copy
       
   124   $ diff ../reference ../post-copy
       
   125 
       
   126 And status thinks the cache is in a proper state
       
   127 
       
   128   $ hg st
       
   129   A dir/o
       
   130   R dir/nested/m
       
   131   ? dir/n
       
   132   ? p
       
   133   ? q
       
   134   $ hg debugstate
       
   135   n 644          0 2000-01-01 00:00:00 dir/b
       
   136   n 644          0 2000-01-01 00:00:00 dir/c
       
   137   n 644          0 2000-01-01 00:00:00 dir/d
       
   138   n 644          0 2000-01-01 00:10:00 dir/i
       
   139   n 644          0 2000-01-01 00:10:00 dir/j
       
   140   n 644          0 2000-01-01 00:00:00 dir/nested/a
       
   141   n 644          0 2000-01-01 00:10:00 dir/nested/h
       
   142   r ?????????????????????????????????? dir/nested/m (glob)
       
   143   a ?????????????????????????????????? dir/o (glob)
       
   144   n 644          0 2000-01-01 00:00:00 dir2/e
       
   145   n 644          0 2000-01-01 00:10:00 dir2/k
       
   146   n 644          0 2000-01-01 00:10:00 dir2/l
       
   147   n 644          0 2000-01-01 00:00:00 f
       
   148   n 644          0 2000-01-01 00:10:00 g
       
   149   $ hg debugstate > ../post-status
       
   150   $ diff ../reference ../post-status
       
   151 
       
   152 Then we can start a status that:
       
   153 - has some update to do (the touch call)
       
   154 - will wait AFTER running status, but before updating the cache on disk
       
   155 
       
   156   $ touch -t 200001010001 dir/c
       
   157   $ hg st >$TESTTMP/status-race-lock.out 2>$TESTTMP/status-race-lock.log \
       
   158   > --config rhg.on-unsupported=abort \
       
   159   > --config devel.sync.status.pre-dirstate-write-file=$TESTTMP/status-race-lock \
       
   160   > &
       
   161   $ $RUNTESTDIR/testlib/wait-on-file 5 $TESTTMP/status-race-lock.waiting
       
   162 
       
   163 We check it runs the status first by modifying a file and updating another timestamp
       
   164 
       
   165   $ touch -t 200001010003 dir/i
       
   166   $ echo babar > dir/j
       
   167   $ touch $TESTTMP/status-race-lock
       
   168   $ wait
       
   169 
       
   170 The test process should have reported a status before the change we made,
       
   171 and should have missed the timestamp update
       
   172 
       
   173   $ cat $TESTTMP/status-race-lock.out
       
   174   A dir/o
       
   175   R dir/nested/m
       
   176   ? dir/n
       
   177   ? p
       
   178   ? q
       
   179   $ cat $TESTTMP/status-race-lock.log
       
   180   $ hg debugstate | grep dir/c
       
   181   n 644          0 2000-01-01 00:01:00 dir/c
       
   182   $ hg debugstate | grep dir/i
       
   183   n 644          0 2000-01-01 00:10:00 dir/i
       
   184   $ hg debugstate | grep dir/j
       
   185   n 644          0 2000-01-01 00:10:00 dir/j
       
   186 
       
   187 final cleanup
       
   188 
       
   189   $ rm $TESTTMP/status-race-lock $TESTTMP/status-race-lock.waiting
       
   190   $ cd ..