Mercurial > hg
comparison tests/run-tests.py @ 21312:986b8a58a6d3
run-tests: move t test parsing into its own function
Test parsing is somewhat complicated. This patch extracts it into its
own function.
The impetus of this patch is folding tsttest() into the TTest class.
Subsequent patches will continue this work until tsttest() no longer
exists.
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Sat, 19 Apr 2014 15:19:28 -0700 |
parents | f9a7018a35ff |
children | a2bd02a3b6d2 |
comparison
equal
deleted
inserted
replaced
21311:f9a7018a35ff | 21312:986b8a58a6d3 |
---|---|
745 return globmatch(el[:-8], l) | 745 return globmatch(el[:-8], l) |
746 if os.altsep and l.replace('\\', '/') == el: | 746 if os.altsep and l.replace('\\', '/') == el: |
747 return '+glob' | 747 return '+glob' |
748 return False | 748 return False |
749 | 749 |
750 def tsttest(test, wd, options, replacements, env): | 750 def tsttest(t, test, wd, options, replacements, env): |
751 # We generate a shell script which outputs unique markers to line | |
752 # up script results with our source. These markers include input | |
753 # line number and the last return code | |
754 salt = "SALT" + str(time.time()) | |
755 def addsalt(line, inpython): | |
756 if inpython: | |
757 script.append('%s %d 0\n' % (salt, line)) | |
758 else: | |
759 script.append('echo %s %s $?\n' % (salt, line)) | |
760 | |
761 # After we run the shell script, we re-unify the script output | |
762 # with non-active parts of the source, with synchronization by our | |
763 # SALT line number markers. The after table contains the | |
764 # non-active components, ordered by line number | |
765 after = {} | |
766 pos = prepos = -1 | |
767 | |
768 # Expected shell script output | |
769 expected = {} | |
770 | |
771 # We keep track of whether or not we're in a Python block so we | |
772 # can generate the surrounding doctest magic | |
773 inpython = False | |
774 | |
775 # True or False when in a true or false conditional section | |
776 skipping = None | |
777 | |
778 def hghave(reqs): | |
779 # TODO: do something smarter when all other uses of hghave is gone | |
780 tdir = TESTDIR.replace('\\', '/') | |
781 proc = Popen4('%s -c "%s/hghave %s"' % | |
782 (options.shell, tdir, ' '.join(reqs)), wd, 0) | |
783 stdout, stderr = proc.communicate() | |
784 ret = proc.wait() | |
785 if wifexited(ret): | |
786 ret = os.WEXITSTATUS(ret) | |
787 if ret == 2: | |
788 print stdout | |
789 sys.exit(1) | |
790 return ret == 0 | |
791 | |
792 f = open(test) | 751 f = open(test) |
793 t = f.readlines() | 752 tlines = f.readlines() |
794 f.close() | 753 f.close() |
795 | 754 |
796 script = [] | 755 salt, script, after, expected = t._parsetest(tlines, wd) |
797 if options.debug: | |
798 script.append('set -x\n') | |
799 if os.getenv('MSYSTEM'): | |
800 script.append('alias pwd="pwd -W"\n') | |
801 n = 0 | |
802 for n, l in enumerate(t): | |
803 if not l.endswith('\n'): | |
804 l += '\n' | |
805 if l.startswith('#if'): | |
806 lsplit = l.split() | |
807 if len(lsplit) < 2 or lsplit[0] != '#if': | |
808 after.setdefault(pos, []).append(' !!! invalid #if\n') | |
809 if skipping is not None: | |
810 after.setdefault(pos, []).append(' !!! nested #if\n') | |
811 skipping = not hghave(lsplit[1:]) | |
812 after.setdefault(pos, []).append(l) | |
813 elif l.startswith('#else'): | |
814 if skipping is None: | |
815 after.setdefault(pos, []).append(' !!! missing #if\n') | |
816 skipping = not skipping | |
817 after.setdefault(pos, []).append(l) | |
818 elif l.startswith('#endif'): | |
819 if skipping is None: | |
820 after.setdefault(pos, []).append(' !!! missing #if\n') | |
821 skipping = None | |
822 after.setdefault(pos, []).append(l) | |
823 elif skipping: | |
824 after.setdefault(pos, []).append(l) | |
825 elif l.startswith(' >>> '): # python inlines | |
826 after.setdefault(pos, []).append(l) | |
827 prepos = pos | |
828 pos = n | |
829 if not inpython: | |
830 # we've just entered a Python block, add the header | |
831 inpython = True | |
832 addsalt(prepos, False) # make sure we report the exit code | |
833 script.append('%s -m heredoctest <<EOF\n' % PYTHON) | |
834 addsalt(n, True) | |
835 script.append(l[2:]) | |
836 elif l.startswith(' ... '): # python inlines | |
837 after.setdefault(prepos, []).append(l) | |
838 script.append(l[2:]) | |
839 elif l.startswith(' $ '): # commands | |
840 if inpython: | |
841 script.append("EOF\n") | |
842 inpython = False | |
843 after.setdefault(pos, []).append(l) | |
844 prepos = pos | |
845 pos = n | |
846 addsalt(n, False) | |
847 cmd = l[4:].split() | |
848 if len(cmd) == 2 and cmd[0] == 'cd': | |
849 l = ' $ cd %s || exit 1\n' % cmd[1] | |
850 script.append(l[4:]) | |
851 elif l.startswith(' > '): # continuations | |
852 after.setdefault(prepos, []).append(l) | |
853 script.append(l[4:]) | |
854 elif l.startswith(' '): # results | |
855 # queue up a list of expected results | |
856 expected.setdefault(pos, []).append(l[2:]) | |
857 else: | |
858 if inpython: | |
859 script.append("EOF\n") | |
860 inpython = False | |
861 # non-command/result - queue up for merged output | |
862 after.setdefault(pos, []).append(l) | |
863 | |
864 if inpython: | |
865 script.append("EOF\n") | |
866 if skipping is not None: | |
867 after.setdefault(pos, []).append(' !!! missing #endif\n') | |
868 addsalt(n + 1, False) | |
869 | 756 |
870 # Write out the script and execute it | 757 # Write out the script and execute it |
871 name = wd + '.sh' | 758 name = wd + '.sh' |
872 f = open(name, 'w') | 759 f = open(name, 'w') |
873 for l in script: | 760 for l in script: |
944 | 831 |
945 class TTest(Test): | 832 class TTest(Test): |
946 """A "t test" is a test backed by a .t file.""" | 833 """A "t test" is a test backed by a .t file.""" |
947 | 834 |
948 def _run(self, testtmp, replacements, env): | 835 def _run(self, testtmp, replacements, env): |
949 return tsttest(self._path, testtmp, self._options, replacements, | 836 return tsttest(self, self._path, testtmp, self._options, replacements, |
950 env) | 837 env) |
838 | |
839 def _hghave(self, reqs, testtmp): | |
840 # TODO do something smarter when all other uses of hghave are gone. | |
841 tdir = TESTDIR.replace('\\', '/') | |
842 proc = Popen4('%s -c "%s/hghave %s"' % | |
843 (self._options.shell, tdir, ' '.join(reqs)), | |
844 testtmp, 0) | |
845 stdout, stderr = proc.communicate() | |
846 ret = proc.wait() | |
847 if wifexited(ret): | |
848 ret = os.WEXITSTATUS(ret) | |
849 if ret == 2: | |
850 print stdout | |
851 sys.exit(1) | |
852 | |
853 return ret == 0 | |
854 | |
855 def _parsetest(self, lines, testtmp): | |
856 # We generate a shell script which outputs unique markers to line | |
857 # up script results with our source. These markers include input | |
858 # line number and the last return code. | |
859 salt = "SALT" + str(time.time()) | |
860 def addsalt(line, inpython): | |
861 if inpython: | |
862 script.append('%s %d 0\n' % (salt, line)) | |
863 else: | |
864 script.append('echo %s %s $?\n' % (salt, line)) | |
865 | |
866 script = [] | |
867 | |
868 # After we run the shell script, we re-unify the script output | |
869 # with non-active parts of the source, with synchronization by our | |
870 # SALT line number markers. The after table contains the non-active | |
871 # components, ordered by line number. | |
872 after = {} | |
873 | |
874 # Expected shell script output. | |
875 expected = {} | |
876 | |
877 pos = prepos = -1 | |
878 | |
879 # True or False when in a true or false conditional section | |
880 skipping = None | |
881 | |
882 # We keep track of whether or not we're in a Python block so we | |
883 # can generate the surrounding doctest magic. | |
884 inpython = False | |
885 | |
886 if self._options.debug: | |
887 script.append('set -x\n') | |
888 if os.getenv('MSYSTEM'): | |
889 script.append('alias pwd="pwd -W"\n') | |
890 | |
891 for n, l in enumerate(lines): | |
892 if not l.endswith('\n'): | |
893 l += '\n' | |
894 if l.startswith('#if'): | |
895 lsplit = l.split() | |
896 if len(lsplit) < 2 or lsplit[0] != '#if': | |
897 after.setdefault(pos, []).append(' !!! invalid #if\n') | |
898 if skipping is not None: | |
899 after.setdefault(pos, []).append(' !!! nested #if\n') | |
900 skipping = not self._hghave(lsplit[1:], testtmp) | |
901 after.setdefault(pos, []).append(l) | |
902 elif l.startswith('#else'): | |
903 if skipping is None: | |
904 after.setdefault(pos, []).append(' !!! missing #if\n') | |
905 skipping = not skipping | |
906 after.setdefault(pos, []).append(l) | |
907 elif l.startswith('#endif'): | |
908 if skipping is None: | |
909 after.setdefault(pos, []).append(' !!! missing #if\n') | |
910 skipping = None | |
911 after.setdefault(pos, []).append(l) | |
912 elif skipping: | |
913 after.setdefault(pos, []).append(l) | |
914 elif l.startswith(' >>> '): # python inlines | |
915 after.setdefault(pos, []).append(l) | |
916 prepos = pos | |
917 pos = n | |
918 if not inpython: | |
919 # We've just entered a Python block. Add the header. | |
920 inpython = True | |
921 addsalt(prepos, False) # Make sure we report the exit code. | |
922 script.append('%s -m heredoctest <<EOF\n' % PYTHON) | |
923 addsalt(n, True) | |
924 script.append(l[2:]) | |
925 elif l.startswith(' ... '): # python inlines | |
926 after.setdefault(prepos, []).append(l) | |
927 script.append(l[2:]) | |
928 elif l.startswith(' $ '): # commands | |
929 if inpython: | |
930 script.append('EOF\n') | |
931 inpython = False | |
932 after.setdefault(pos, []).append(l) | |
933 prepos = pos | |
934 pos = n | |
935 addsalt(n, False) | |
936 cmd = l[4:].split() | |
937 if len(cmd) == 2 and cmd[0] == 'cd': | |
938 l = ' $ cd %s || exit 1\n' % cmd[1] | |
939 script.append(l[4:]) | |
940 elif l.startswith(' > '): # continuations | |
941 after.setdefault(prepos, []).append(l) | |
942 script.append(l[4:]) | |
943 elif l.startswith(' '): # results | |
944 # Queue up a list of expected results. | |
945 expected.setdefault(pos, []).append(l[2:]) | |
946 else: | |
947 if inpython: | |
948 script.append('EOF\n') | |
949 inpython = False | |
950 # Non-command/result. Queue up for merged output. | |
951 after.setdefault(pos, []).append(l) | |
952 | |
953 if inpython: | |
954 script.append('EOF\n') | |
955 if skipping is not None: | |
956 after.setdefault(pos, []).append(' !!! missing #endif\n') | |
957 addsalt(n + 1, False) | |
958 | |
959 return salt, script, after, expected | |
960 | |
951 | 961 |
952 wifexited = getattr(os, "WIFEXITED", lambda x: False) | 962 wifexited = getattr(os, "WIFEXITED", lambda x: False) |
953 def run(cmd, wd, options, replacements, env): | 963 def run(cmd, wd, options, replacements, env): |
954 """Run command in a sub-process, capturing the output (stdout and stderr). | 964 """Run command in a sub-process, capturing the output (stdout and stderr). |
955 Return a tuple (exitcode, output). output is None in debug mode.""" | 965 Return a tuple (exitcode, output). output is None in debug mode.""" |