1"""Tests for distutils.cygwinccompiler."""
2import unittest
3import sys
4import os
5from io import BytesIO
6from test.support import run_unittest
7
8from distutils import cygwinccompiler
9from distutils.cygwinccompiler import (check_config_h,
10                                       CONFIG_H_OK, CONFIG_H_NOTOK,
11                                       CONFIG_H_UNCERTAIN, get_versions,
12                                       get_msvcr)
13from distutils.tests import support
14
15class FakePopen(object):
16    test_class = None
17
18    def __init__(self, cmd, shell, stdout):
19        self.cmd = cmd.split()[0]
20        exes = self.test_class._exes
21        if self.cmd in exes:
22            # issue #6438 in Python 3.x, Popen returns bytes
23            self.stdout = BytesIO(exes[self.cmd])
24        else:
25            self.stdout = os.popen(cmd, 'r')
26
27
28class CygwinCCompilerTestCase(support.TempdirManager,
29                              unittest.TestCase):
30
31    def setUp(self):
32        super(CygwinCCompilerTestCase, self).setUp()
33        self.version = sys.version
34        self.python_h = os.path.join(self.mkdtemp(), 'python.h')
35        from distutils import sysconfig
36        self.old_get_config_h_filename = sysconfig.get_config_h_filename
37        sysconfig.get_config_h_filename = self._get_config_h_filename
38        self.old_find_executable = cygwinccompiler.find_executable
39        cygwinccompiler.find_executable = self._find_executable
40        self._exes = {}
41        self.old_popen = cygwinccompiler.Popen
42        FakePopen.test_class = self
43        cygwinccompiler.Popen = FakePopen
44
45    def tearDown(self):
46        sys.version = self.version
47        from distutils import sysconfig
48        sysconfig.get_config_h_filename = self.old_get_config_h_filename
49        cygwinccompiler.find_executable = self.old_find_executable
50        cygwinccompiler.Popen = self.old_popen
51        super(CygwinCCompilerTestCase, self).tearDown()
52
53    def _get_config_h_filename(self):
54        return self.python_h
55
56    def _find_executable(self, name):
57        if name in self._exes:
58            return name
59        return None
60
61    def test_check_config_h(self):
62
63        # check_config_h looks for "GCC" in sys.version first
64        # returns CONFIG_H_OK if found
65        sys.version = ('2.6.1 (r261:67515, Dec  6 2008, 16:42:21) \n[GCC '
66                       '4.0.1 (Apple Computer, Inc. build 5370)]')
67
68        self.assertEqual(check_config_h()[0], CONFIG_H_OK)
69
70        # then it tries to see if it can find "__GNUC__" in pyconfig.h
71        sys.version = 'something without the *CC word'
72
73        # if the file doesn't exist it returns  CONFIG_H_UNCERTAIN
74        self.assertEqual(check_config_h()[0], CONFIG_H_UNCERTAIN)
75
76        # if it exists but does not contain __GNUC__, it returns CONFIG_H_NOTOK
77        self.write_file(self.python_h, 'xxx')
78        self.assertEqual(check_config_h()[0], CONFIG_H_NOTOK)
79
80        # and CONFIG_H_OK if __GNUC__ is found
81        self.write_file(self.python_h, 'xxx __GNUC__ xxx')
82        self.assertEqual(check_config_h()[0], CONFIG_H_OK)
83
84    def test_get_versions(self):
85
86        # get_versions calls distutils.spawn.find_executable on
87        # 'gcc', 'ld' and 'dllwrap'
88        self.assertEqual(get_versions(), (None, None, None))
89
90        # Let's fake we have 'gcc' and it returns '3.4.5'
91        self._exes['gcc'] = b'gcc (GCC) 3.4.5 (mingw special)\nFSF'
92        res = get_versions()
93        self.assertEqual(str(res[0]), '3.4.5')
94
95        # and let's see what happens when the version
96        # doesn't match the regular expression
97        # (\d+\.\d+(\.\d+)*)
98        self._exes['gcc'] = b'very strange output'
99        res = get_versions()
100        self.assertEqual(res[0], None)
101
102        # same thing for ld
103        self._exes['ld'] = b'GNU ld version 2.17.50 20060824'
104        res = get_versions()
105        self.assertEqual(str(res[1]), '2.17.50')
106        self._exes['ld'] = b'@(#)PROGRAM:ld  PROJECT:ld64-77'
107        res = get_versions()
108        self.assertEqual(res[1], None)
109
110        # and dllwrap
111        self._exes['dllwrap'] = b'GNU dllwrap 2.17.50 20060824\nFSF'
112        res = get_versions()
113        self.assertEqual(str(res[2]), '2.17.50')
114        self._exes['dllwrap'] = b'Cheese Wrap'
115        res = get_versions()
116        self.assertEqual(res[2], None)
117
118    def test_get_msvcr(self):
119
120        # none
121        sys.version  = ('2.6.1 (r261:67515, Dec  6 2008, 16:42:21) '
122                        '\n[GCC 4.0.1 (Apple Computer, Inc. build 5370)]')
123        self.assertEqual(get_msvcr(), None)
124
125        # MSVC 7.0
126        sys.version = ('2.5.1 (r251:54863, Apr 18 2007, 08:51:08) '
127                       '[MSC v.1300 32 bits (Intel)]')
128        self.assertEqual(get_msvcr(), ['msvcr70'])
129
130        # MSVC 7.1
131        sys.version = ('2.5.1 (r251:54863, Apr 18 2007, 08:51:08) '
132                       '[MSC v.1310 32 bits (Intel)]')
133        self.assertEqual(get_msvcr(), ['msvcr71'])
134
135        # VS2005 / MSVC 8.0
136        sys.version = ('2.5.1 (r251:54863, Apr 18 2007, 08:51:08) '
137                       '[MSC v.1400 32 bits (Intel)]')
138        self.assertEqual(get_msvcr(), ['msvcr80'])
139
140        # VS2008 / MSVC 9.0
141        sys.version = ('2.5.1 (r251:54863, Apr 18 2007, 08:51:08) '
142                       '[MSC v.1500 32 bits (Intel)]')
143        self.assertEqual(get_msvcr(), ['msvcr90'])
144
145        # unknown
146        sys.version = ('2.5.1 (r251:54863, Apr 18 2007, 08:51:08) '
147                       '[MSC v.1999 32 bits (Intel)]')
148        self.assertRaises(ValueError, get_msvcr)
149
150def test_suite():
151    return unittest.makeSuite(CygwinCCompilerTestCase)
152
153if __name__ == '__main__':
154    run_unittest(test_suite())
155