~ubuntu-branches/debian/sid/subversion/sid

« back to all changes in this revision

Viewing changes to subversion/tests/cmdline/special_tests.py

  • Committer: Package Import Robot
  • Author(s): James McCoy
  • Date: 2015-08-07 21:32:47 UTC
  • mfrom: (0.2.15) (4.1.7 experimental)
  • Revision ID: package-import@ubuntu.com-20150807213247-ozyewtmgsr6tkewl
Tags: 1.9.0-1
* Upload to unstable
* New upstream release.
  + Security fixes
    - CVE-2015-3184: Mixed anonymous/authenticated path-based authz with
      httpd 2.4
    - CVE-2015-3187: svn_repos_trace_node_locations() reveals paths hidden
      by authz
* Add >= 2.7 requirement for python-all-dev Build-Depends, needed to run
  tests.
* Remove Build-Conflicts against ruby-test-unit.  (Closes: #791844)
* Remove patches/apache_module_dependency in favor of expressing the
  dependencies in authz_svn.load/dav_svn.load.
* Build-Depend on apache2-dev (>= 2.4.16) to ensure ap_some_authn_required()
  is available when building mod_authz_svn and Depend on apache2-bin (>=
  2.4.16) for runtime support.

Show diffs side-by-side

added added

removed removed

Lines of Context:
86
86
    })
87
87
 
88
88
  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
89
 
                                        expected_status, None,
90
 
                                        wc_dir)
 
89
                                        expected_status)
91
90
 
92
91
  ## Now we should update to the previous version, verify that no
93
92
  ## symlink is present, then update back to HEAD and see if the symlink
94
93
  ## is regenerated properly.
95
 
  svntest.actions.run_and_verify_svn(None, None, [],
 
94
  svntest.actions.run_and_verify_svn(None, [],
96
95
                                     'up', '-r', '1', wc_dir)
97
96
 
98
97
  # Is the symlink gone?
99
98
  if os.path.isfile(newfile_path) or os.path.islink(newfile_path):
100
99
    raise svntest.Failure
101
100
 
102
 
  svntest.actions.run_and_verify_svn(None, None, [],
 
101
  svntest.actions.run_and_verify_svn(None, [],
103
102
                                     'up', '-r', '2', wc_dir)
104
103
 
105
104
  # Is the symlink back?
118
117
 
119
118
  was_cwd = os.getcwd()
120
119
  os.chdir(wc_dir)
121
 
  svntest.actions.run_and_verify_svn(None, [ "M       newfile\n" ], [], 'st')
 
120
  svntest.actions.run_and_verify_svn([ "M       newfile\n" ], [], 'st')
122
121
 
123
122
  os.chdir(was_cwd)
124
123
 
133
132
    })
134
133
 
135
134
  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
136
 
                                        expected_status, None, wc_dir)
 
135
                                        expected_status)
137
136
 
138
137
 
139
138
@SkipUnless(svntest.main.is_posix_os)
152
151
  # Does status show the obstruction?
153
152
  was_cwd = os.getcwd()
154
153
  os.chdir(wc_dir)
155
 
  svntest.actions.run_and_verify_svn(None, [ "~       iota\n" ], [], 'st')
 
154
  svntest.actions.run_and_verify_svn([ "~       iota\n" ], [], 'st')
156
155
 
157
156
  # And does a commit fail?
158
157
  os.chdir(was_cwd)
183
182
  # import this symlink into the repository
184
183
  url = sbox.repo_url + "/dirA/dirB/new_link"
185
184
  exit_code, output, errput = svntest.actions.run_and_verify_svn(
186
 
    'Import a symlink', None, [], 'import',
 
185
    None, [], 'import',
187
186
    '-m', 'log msg', new_path, url)
188
187
 
189
188
  regex = "(Committed|Imported) revision [0-9]+."
197
196
  os.remove(new_path)
198
197
 
199
198
  # run update and verify that the symlink is put back into place
200
 
  svntest.actions.run_and_verify_svn(None, None, [],
 
199
  svntest.actions.run_and_verify_svn(None, [],
201
200
                                     'up', wc_dir)
202
201
 
203
202
  # Is the symlink back?
213
212
  for export_src, dest_dir in [(sbox.wc_dir, 'export-wc'),
214
213
                               (sbox.repo_url, 'export-url')]:
215
214
    export_target = sbox.add_wc_path(dest_dir)
216
 
    svntest.actions.run_and_verify_svn(None, None, [],
 
215
    svntest.actions.run_and_verify_svn(None, [],
217
216
                                       'export', export_src, export_target)
218
217
 
219
218
    # is the link at the correct place?
250
249
    })
251
250
 
252
251
  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
253
 
                                        expected_status, None, wc_dir)
 
252
                                        expected_status)
254
253
  # Copy H to H2
255
254
  H_path = os.path.join(wc_dir, 'A', 'D', 'H')
256
255
  H2_path = os.path.join(wc_dir, 'A', 'D', 'H2')
257
 
  svntest.actions.run_and_verify_svn(None, None, [], 'cp', H_path, H2_path)
 
256
  svntest.actions.run_and_verify_svn(None, [], 'cp', H_path, H2_path)
258
257
 
259
258
  # 'svn status' should show just "A/D/H2  A +".  Nothing broken.
260
259
  expected_status.add({
297
296
    })
298
297
 
299
298
  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
300
 
                                        expected_status, None, wc_dir)
 
299
                                        expected_status)
301
300
 
302
301
 
303
302
  # Now replace the symlink with a normal file and try to commit, we
308
307
  # Does status show the obstruction?
309
308
  was_cwd = os.getcwd()
310
309
  os.chdir(wc_dir)
311
 
  svntest.actions.run_and_verify_svn(None, [ "~       newfile\n" ], [], 'st')
 
310
  svntest.actions.run_and_verify_svn([ "~       newfile\n" ], [], 'st')
312
311
 
313
312
  # And does a commit fail?
314
313
  os.chdir(was_cwd)
350
349
    })
351
350
 
352
351
  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
353
 
                                        expected_status, None, wc_dir)
 
352
                                        expected_status)
354
353
 
355
354
  # Now remove it
356
 
  svntest.actions.run_and_verify_svn(None, None, [], 'rm', newfile_path)
 
355
  svntest.actions.run_and_verify_svn(None, [], 'rm', newfile_path)
357
356
 
358
357
  # Commit and verify that it worked
359
358
  expected_output = svntest.wc.State(wc_dir, {
366
365
    })
367
366
 
368
367
  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
369
 
                                        expected_status, None, wc_dir)
 
368
                                        expected_status)
370
369
 
371
370
#----------------------------------------------------------------------
372
371
@SkipUnless(server_has_mergeinfo)
395
394
    'A/Dprime/gamma' : Item(verb='Deleting'),
396
395
    })
397
396
 
398
 
  svntest.actions.run_and_verify_commit(wc_dir, expected_output, None, None,
399
 
                                        wc_dir)
 
397
  svntest.actions.run_and_verify_commit(wc_dir, expected_output, None)
400
398
 
401
399
  # Commit a symlink in its place
402
400
  linktarget_path = os.path.join(wc_dir, 'linktarget')
407
405
    'A/Dprime/gamma' : Item(verb='Adding'),
408
406
    })
409
407
 
410
 
  svntest.actions.run_and_verify_commit(wc_dir, expected_output, None, None,
411
 
                                        wc_dir)
 
408
  svntest.actions.run_and_verify_commit(wc_dir, expected_output, None)
412
409
 
413
410
  # merge the creation of the symlink into the original directory
414
411
  svntest.main.run_svn(None,
430
427
    'A/D/gamma' : Item(verb='Replacing'),
431
428
    })
432
429
 
433
 
  svntest.actions.run_and_verify_commit(wc_dir, expected_output, None, None,
434
 
                                        wc_dir)
 
430
  svntest.actions.run_and_verify_commit(wc_dir, expected_output, None)
435
431
 
436
432
 
437
433
 
460
456
    'A/Dprime/gamma' : Item(verb='Deleting'),
461
457
    })
462
458
 
463
 
  svntest.actions.run_and_verify_commit(wc_dir, expected_output, None, None,
464
 
                                        wc_dir)
 
459
  svntest.actions.run_and_verify_commit(wc_dir, expected_output, None)
465
460
 
466
461
  # Commit a symlink in its place
467
462
  linktarget_path = os.path.join(wc_dir, 'linktarget')
472
467
    'A/Dprime/gamma' : Item(verb='Adding'),
473
468
    })
474
469
 
475
 
  svntest.actions.run_and_verify_commit(wc_dir, expected_output, None, None,
476
 
                                        wc_dir)
 
470
  svntest.actions.run_and_verify_commit(wc_dir, expected_output, None)
477
471
 
478
472
  svntest.main.file_write(gamma_path, 'changed file', 'w+')
479
473
 
481
475
    'A/D/gamma' : Item(verb='Sending'),
482
476
    })
483
477
 
484
 
  svntest.actions.run_and_verify_commit(wc_dir, expected_output, None, None,
485
 
                                        wc_dir)
 
478
  svntest.actions.run_and_verify_commit(wc_dir, expected_output, None)
486
479
 
487
480
  # ok, now merge the change to the file into the symlink we created, this
488
481
  # gives us a weird error
498
491
 
499
492
  svntest.actions.load_repo(sbox, os.path.join(os.path.dirname(sys.argv[0]),
500
493
                                               'special_tests_data',
501
 
                                               'symlink.dump'))
 
494
                                               'symlink.dump'),
 
495
                            create_wc=False)
502
496
 
503
497
  expected_output = svntest.wc.State(sbox.wc_dir, {
504
498
    'from': Item(status='A '),
537
531
  expected_output = [
538
532
    "Index: link\n",
539
533
    "===================================================================\n",
540
 
    "--- link\t(revision 0)\n",
 
534
    "--- link\t(nonexistent)\n",
541
535
    "+++ link\t(working copy)\n",
542
536
    "@@ -0,0 +1 @@\n",
543
537
    "+link A/D\n",
550
544
    "+*\n",
551
545
    "\\ No newline at end of property\n"
552
546
  ]
553
 
  svntest.actions.run_and_verify_svn(None, expected_output, [], 'diff',
 
547
  svntest.actions.run_and_verify_svn(expected_output, [], 'diff',
554
548
                                     '.')
555
549
  # We should get the same output if we the diff the symlink itself.
556
 
  svntest.actions.run_and_verify_svn(None, expected_output, [], 'diff', 'link')
 
550
  svntest.actions.run_and_verify_svn(expected_output, [], 'diff', 'link')
557
551
 
558
552
#----------------------------------------------------------------------
559
553
# Issue 2692 (part of): Check that the client can check out a repository
564
558
 
565
559
  svntest.actions.load_repo(sbox, os.path.join(os.path.dirname(sys.argv[0]),
566
560
                                               'special_tests_data',
567
 
                                               'bad-special-type.dump'))
 
561
                                               'bad-special-type.dump'),
 
562
                            create_wc=False)
568
563
 
569
564
  expected_output = svntest.wc.State(sbox.wc_dir, {
570
565
    'special': Item(status='A '),
595
590
  # Does status show the obstruction?
596
591
  was_cwd = os.getcwd()
597
592
  os.chdir(wc_dir)
598
 
  svntest.actions.run_and_verify_svn(None, [ "~       from\n" ], [], 'st')
 
593
  svntest.actions.run_and_verify_svn([ "~       from\n" ], [], 'st')
599
594
 
600
595
  # The commit shouldn't do anything.
601
596
  # I'd expect a failed commit here, but replacing a file locally with a
604
599
  expected_output = svntest.wc.State(wc_dir, {
605
600
  })
606
601
 
607
 
  error_re_string = 'E145001: (Entry|Node).*has.*changed (special|kind)'
 
602
  error_re_string = '.*E145001: (Entry|Node).*has.*changed (special|kind).*'
608
603
 
609
604
  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
610
 
                                        None, error_re_string, wc_dir)
 
605
                                        None, error_re_string)
611
606
 
612
607
# test for issue #1808: svn up deletes local symlink that obstructs
613
608
# versioned file
614
609
@Issue(1808)
615
 
@SkipUnless(svntest.main.is_posix_os)
616
610
def update_obstructing_symlink(sbox):
617
611
  "symlink obstructs incoming delete"
618
612
 
619
613
  sbox.build()
620
614
  wc_dir = sbox.wc_dir
621
 
  mu_path = os.path.join(wc_dir, 'A', 'mu')
622
 
  mu_url = sbox.repo_url + '/A/mu'
623
 
  iota_path = os.path.join(wc_dir, 'iota')
624
 
 
625
 
  # delete A/mu and replace it with a symlink
626
 
  svntest.main.run_svn(None, 'rm', mu_path)
627
 
  os.symlink(iota_path, mu_path)
628
 
 
629
 
  svntest.main.run_svn(None, 'rm', mu_url,
630
 
                       '-m', 'log msg')
631
 
 
632
 
  svntest.main.run_svn(None,
633
 
                       'up', wc_dir)
 
615
  mu_path = sbox.ospath('A/mu')
 
616
 
 
617
  iota_abspath = os.path.abspath(sbox.ospath('iota'))
 
618
 
 
619
  # delete mu and replace it with an (not-added) symlink
 
620
  sbox.simple_rm('A/mu')
 
621
  sbox.simple_symlink(iota_abspath, 'A/mu')
 
622
 
 
623
  # delete pi and replace it with an added symlink
 
624
  sbox.simple_rm('A/D/G/pi')
 
625
  sbox.simple_add_symlink(iota_abspath, 'A/D/G/pi')
 
626
 
 
627
  if not os.path.exists(mu_path):
 
628
      raise svntest.Failure("mu should be there")
 
629
 
 
630
  # Now remove mu and pi in the repository
 
631
  svntest.main.run_svn(None, 'rm', '-m', 'log msg',
 
632
                       sbox.repo_url + '/A/mu',
 
633
                       sbox.repo_url + '/A/D/G/pi')
 
634
 
 
635
  # We expect tree conflicts
 
636
  expected_output = svntest.wc.State(wc_dir, {
 
637
    'A/mu':         Item(status='  ', treeconflict='C'),
 
638
    'A/D/G/pi':     Item(status='  ', treeconflict='C')
 
639
  })
 
640
 
 
641
  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
 
642
  expected_status.tweak('A/mu', status='? ', treeconflict='C',
 
643
                        wc_rev=None)
 
644
 
 
645
  expected_status.tweak('A/D/G/pi', status='A ',treeconflict='C',
 
646
                        wc_rev='-')
 
647
 
 
648
  svntest.actions.run_and_verify_update(wc_dir,
 
649
                                        expected_output, None,
 
650
                                        expected_status)
 
651
 
 
652
  expected_info = [
 
653
    {
 
654
      'Path': re.escape(sbox.ospath('A/D/G/pi')),
 
655
      'Tree conflict': 'local file replace, incoming file delete or move.*'
 
656
    },
 
657
    {
 
658
      'Path': re.escape(sbox.ospath('A/mu')),
 
659
      'Tree conflict': 'local file delete, incoming file delete or move.*'
 
660
    }
 
661
  ]
 
662
 
 
663
  svntest.actions.run_and_verify_info(expected_info,
 
664
                                      sbox.ospath('A/D/G/pi'),
 
665
                                      sbox.ospath('A/mu'))
634
666
 
635
667
  # check that the symlink is still there
636
 
  target = os.readlink(mu_path)
637
 
  if target != iota_path:
638
 
    raise svntest.Failure
639
 
 
 
668
  if not os.path.exists(mu_path):
 
669
      raise svntest.Failure("mu should be there")
 
670
  if svntest.main.is_posix_os():
 
671
    target = os.readlink(mu_path)
 
672
    if target != iota_abspath:
 
673
      raise svntest.Failure("mu no longer points to the same location")
640
674
 
641
675
def warn_on_reserved_name(sbox):
642
676
  "warn when attempt operation on a reserved name"
643
677
  sbox.build()
644
678
  reserved_path = os.path.join(sbox.wc_dir, svntest.main.get_admin_name())
645
679
  svntest.actions.run_and_verify_svn(
646
 
    "Locking a file with a reserved name failed to result in an error",
647
680
    None,
648
681
    ".*Skipping argument: E200025: '.+' ends in a reserved name.*",
649
682
    'lock', reserved_path)
666
699
 
667
700
  # Property value should be SVN_PROP_BOOLEAN_TRUE
668
701
  expected_propval = ['*']
669
 
  svntest.actions.run_and_verify_svn(None, expected_propval, [],
670
 
                                     'propget', '--strict', 'svn:special',
 
702
  svntest.actions.run_and_verify_svn(expected_propval, [],
 
703
                                     'propget', '--no-newline', 'svn:special',
671
704
                                     iota2_path)
672
705
 
673
706
  # Commit and check again.
679
712
    'iota2' : Item(status='  ', wc_rev=2),
680
713
    })
681
714
  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
682
 
                                        expected_status, None,
683
 
                                        wc_dir)
 
715
                                        expected_status)
684
716
 
685
717
  svntest.main.run_svn(None, 'update', wc_dir)
686
 
  svntest.actions.run_and_verify_svn(None, expected_propval, [],
687
 
                                     'propget', '--strict', 'svn:special',
 
718
  svntest.actions.run_and_verify_svn(expected_propval, [],
 
719
                                     'propget', '--no-newline', 'svn:special',
688
720
                                     iota2_path)
689
721
 
690
722
 
702
734
  os.unlink('psi')
703
735
  os.symlink('omega', 'psi') # omega is versioned!
704
736
  svntest.main.run_svn(None, 'changelist', 'chi cl', 'chi')
705
 
  svntest.actions.run_and_verify_svn(None, None, [], 'commit',
 
737
  svntest.actions.run_and_verify_svn(None, [], 'commit',
706
738
                                     '--changelist', 'chi cl',
707
739
                                     '-m', 'psi changed special status')
708
740
 
728
760
    })
729
761
 
730
762
  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
731
 
                                        expected_status, None, wc_dir)
 
763
                                        expected_status)
732
764
 
733
765
  # Modify the symlink to point somewhere else
734
766
  os.remove(newfile_path)
746
778
  svntest.actions.run_and_verify_status(wc_dir, expected_status)
747
779
 
748
780
  # Issue 3972, repeat revert produces no output
749
 
  svntest.actions.run_and_verify_svn(None, [], [], 'revert', '-R', wc_dir)
 
781
  svntest.actions.run_and_verify_svn([], [], 'revert', '-R', wc_dir)
750
782
  svntest.actions.run_and_verify_status(wc_dir, expected_status)
751
783
 
752
784
  # Now replace the symlink with a normal file and try to commit, we
850
882
  symlink_basename = os.path.basename(symlink_path)
851
883
 
852
884
  # Some basic tests
853
 
  svntest.actions.run_and_verify_svnversion("Unmodified symlink to wc",
854
 
                                            symlink_path, sbox.repo_url,
 
885
  svntest.actions.run_and_verify_svnversion(symlink_path, sbox.repo_url,
855
886
                                            [ "1\n" ], [])
856
887
 
857
888
#----------------------------------------------------------------------
901
932
                                        expected_output,
902
933
                                        expected_disk,
903
934
                                        expected_status,
904
 
                                        None, None, None,
905
 
                                        None, None, 1)
 
935
                                        check_props=True)
906
936
 
907
937
#----------------------------------------------------------------------
908
938
@Issue(4091)
1108
1138
 
1109
1139
  kappa_path = sbox.ospath('kappa')
1110
1140
  sbox.simple_add_symlink('iota', 'kappa')
1111
 
  svntest.actions.run_and_verify_svn(None, "link iota", [],
 
1141
  svntest.actions.run_and_verify_svn("link iota", [],
1112
1142
                                     "cat", kappa_path)
1113
1143
 
1114
1144
#----------------------------------------------------------------------
1144
1174
    's-in-place'        : Item(verb='Sending'),
1145
1175
  })
1146
1176
  svntest.actions.run_and_verify_commit(wc_dir,
1147
 
                                        expected_output, None, None,
1148
 
                                        wc_dir)
 
1177
                                        expected_output, None)
1149
1178
 
1150
1179
  # r4
1151
1180
  svntest.main.run_svnmucc('propdel', 'svn:special',
1176
1205
                                        expected_output,
1177
1206
                                        None,
1178
1207
                                        expected_status,
1179
 
                                        None, None, None, None, None,
1180
1208
                                        check_props=True)
1181
1209
 
1182
1210
  # Update back to r2, to prepare some local changes
1193
1221
                                        expected_output,
1194
1222
                                        None,
1195
1223
                                        expected_status,
1196
 
                                        None, None, None, None, None,
1197
 
                                        True,
 
1224
                                        [], True,
1198
1225
                                        wc_dir, '-r', '2')
1199
1226
 
1200
1227
  # Ok, now add a property on all of them to make future symlinkness changes
1218
1245
                                        expected_output,
1219
1246
                                        None,
1220
1247
                                        expected_status,
1221
 
                                        None, None, None, None, None,
1222
 
                                        True)
 
1248
                                        check_props=True)
 
1249
 
 
1250
#----------------------------------------------------------------------
 
1251
@Issue(4479)
 
1252
def multiline_special(sbox):
 
1253
  "multiline file with svn:special"
 
1254
 
 
1255
  sbox.build()
 
1256
  wc_dir = sbox.wc_dir
 
1257
 
 
1258
  sbox.simple_append('iota', 'A second line.\n')
 
1259
  sbox.simple_commit();
 
1260
  tmp = sbox.get_tempname()
 
1261
  svntest.main.file_write(tmp, '*', 'w+')
 
1262
  svntest.main.run_svnmucc('propsetf', 'svn:special', tmp,
 
1263
                           sbox.repo_url + '/iota',
 
1264
                           '-m', 'set svn:special')
 
1265
 
 
1266
  sbox.simple_update(revision=1);
 
1267
  sbox.simple_update();
 
1268
 
 
1269
  expected_disk = svntest.main.greek_state.copy()
 
1270
  expected_disk.tweak()
 
1271
  expected_disk.tweak('iota',
 
1272
                      contents="This is the file 'iota'.\nA second line.\n",
 
1273
                      props={'svn:special' : '*'})
 
1274
  svntest.actions.verify_disk(wc_dir, expected_disk.old_tree(), True)
 
1275
 
 
1276
#----------------------------------------------------------------------
 
1277
@Issue(4482)
 
1278
@XFail(svntest.main.is_posix_os)
 
1279
def multiline_symlink_special(sbox):
 
1280
  "multiline link file with svn:special"
 
1281
 
 
1282
  sbox.build()
 
1283
  wc_dir = sbox.wc_dir
 
1284
 
 
1285
  sbox.simple_append('dodgy-link1', 'link foo\n')
 
1286
  sbox.simple_append('dodgy-link2', 'link foo\nbar\n')
 
1287
  svntest.main.run_svnmucc('put', sbox.ospath('dodgy-link1'), 'dodgy-link1',
 
1288
                           'put', sbox.ospath('dodgy-link2'), 'dodgy-link2',
 
1289
                           'propset', 'svn:special', 'X', 'dodgy-link1',
 
1290
                           'propset', 'svn:special', 'X', 'dodgy-link2',
 
1291
                           '-U', sbox.repo_url,
 
1292
                           '-m', 'Create dodgy symlinks')
 
1293
  os.remove(sbox.ospath('dodgy-link1'))
 
1294
  os.remove(sbox.ospath('dodgy-link2'))
 
1295
 
 
1296
  sbox.simple_update();
 
1297
 
 
1298
  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
 
1299
  expected_status.add({
 
1300
      'dodgy-link1' : Item(status='  ', wc_rev=2),
 
1301
      'dodgy-link2' : Item(status='  ', wc_rev=2),
 
1302
      })
 
1303
  # XFAIL: Only content before \n used when creating the link but all
 
1304
  # content used when detecting modifications, so the pristine working
 
1305
  # copy shows up as modified.
 
1306
  svntest.actions.run_and_verify_status(wc_dir, expected_status)
1223
1307
 
1224
1308
########################################################################
1225
1309
# Run the tests
1252
1336
              externals_as_symlink_targets,
1253
1337
              cat_added_symlink,
1254
1338
              incoming_symlink_changes,
 
1339
              multiline_special,
 
1340
              multiline_symlink_special,
1255
1341
             ]
1256
1342
 
1257
1343
if __name__ == '__main__':