]>
Commit | Line | Data |
---|---|---|
9da7846c SB |
1 | # @file CharEncodingCheck.py\r |
2 | #\r | |
3 | # Copyright (c) Microsoft Corporation.\r | |
4 | # SPDX-License-Identifier: BSD-2-Clause-Patent\r | |
5 | ##\r | |
6 | \r | |
7 | \r | |
8 | import os\r | |
9 | import logging\r | |
10 | from edk2toolext.environment.plugintypes.ci_build_plugin import ICiBuildPlugin\r | |
11 | from edk2toolext.environment.var_dict import VarDict\r | |
12 | \r | |
13 | ##\r | |
14 | # map\r | |
15 | ##\r | |
16 | EcodingMap = {\r | |
17 | ".md": 'utf-8',\r | |
18 | ".dsc": 'utf-8',\r | |
19 | ".dec": 'utf-8',\r | |
20 | ".c": 'utf-8',\r | |
21 | ".h": 'utf-8',\r | |
22 | ".asm": 'utf-8',\r | |
23 | ".masm": 'utf-8',\r | |
24 | ".nasm": 'utf-8',\r | |
25 | ".s": 'utf-8',\r | |
26 | ".inf": 'utf-8',\r | |
27 | ".asl": 'utf-8',\r | |
28 | ".uni": 'utf-8',\r | |
29 | ".py": 'utf-8'\r | |
30 | }\r | |
31 | \r | |
32 | \r | |
33 | class CharEncodingCheck(ICiBuildPlugin):\r | |
34 | """\r | |
35 | A CiBuildPlugin that scans each file in the code tree and confirms the encoding is correct.\r | |
36 | \r | |
37 | Configuration options:\r | |
38 | "CharEncodingCheck": {\r | |
39 | "IgnoreFiles": []\r | |
40 | }\r | |
41 | """\r | |
42 | \r | |
43 | def GetTestName(self, packagename: str, environment: VarDict) -> tuple:\r | |
44 | """ Provide the testcase name and classname for use in reporting\r | |
45 | testclassname: a descriptive string for the testcase can include whitespace\r | |
46 | classname: should be patterned <packagename>.<plugin>.<optionally any unique condition>\r | |
47 | \r | |
48 | Args:\r | |
49 | packagename: string containing name of package to build\r | |
50 | environment: The VarDict for the test to run in\r | |
51 | Returns:\r | |
52 | a tuple containing the testcase name and the classname\r | |
53 | (testcasename, classname)\r | |
54 | """\r | |
55 | return ("Check for valid file encoding for " + packagename, packagename + ".CharEncodingCheck")\r | |
56 | \r | |
57 | ##\r | |
58 | # External function of plugin. This function is used to perform the task of the ci_build_plugin Plugin\r | |
59 | #\r | |
60 | # - package is the edk2 path to package. This means workspace/packagepath relative.\r | |
61 | # - edk2path object configured with workspace and packages path\r | |
62 | # - PkgConfig Object (dict) for the pkg\r | |
63 | # - EnvConfig Object\r | |
64 | # - Plugin Manager Instance\r | |
65 | # - Plugin Helper Obj Instance\r | |
66 | # - Junit Logger\r | |
67 | # - output_stream the StringIO output stream from this plugin via logging\r | |
68 | def RunBuildPlugin(self, packagename, Edk2pathObj, pkgconfig, environment, PLM, PLMHelper, tc, output_stream=None):\r | |
69 | overall_status = 0\r | |
70 | files_tested = 0\r | |
71 | \r | |
2aac8bb7 | 72 | abs_pkg_path = Edk2pathObj.GetAbsolutePathOnThisSystemFromEdk2RelativePath(packagename)\r |
9da7846c SB |
73 | \r |
74 | if abs_pkg_path is None:\r | |
75 | tc.SetSkipped()\r | |
76 | tc.LogStdError("No Package folder {0}".format(abs_pkg_path))\r | |
77 | return 0\r | |
78 | \r | |
79 | for (ext, enc) in EcodingMap.items():\r | |
80 | files = self.WalkDirectoryForExtension([ext], abs_pkg_path)\r | |
81 | files = [Edk2pathObj.GetEdk2RelativePathFromAbsolutePath(x) for x in files] # make edk2relative path so can process ignores\r | |
82 | \r | |
83 | if "IgnoreFiles" in pkgconfig:\r | |
84 | for a in pkgconfig["IgnoreFiles"]:\r | |
85 | a = a.replace(os.sep, "/")\r | |
86 | try:\r | |
87 | tc.LogStdOut("Ignoring File {0}".format(a))\r | |
88 | files.remove(a)\r | |
89 | except:\r | |
90 | tc.LogStdError("CharEncodingCheck.IgnoreInf -> {0} not found in filesystem. Invalid ignore file".format(a))\r | |
91 | logging.info("CharEncodingCheck.IgnoreInf -> {0} not found in filesystem. Invalid ignore file".format(a))\r | |
92 | \r | |
2aac8bb7 | 93 | files = [Edk2pathObj.GetAbsolutePathOnThisSystemFromEdk2RelativePath(x) for x in files]\r |
9da7846c SB |
94 | for a in files:\r |
95 | files_tested += 1\r | |
96 | if(self.TestEncodingOk(a, enc)):\r | |
97 | logging.debug("File {0} Passed Encoding Check {1}".format(a, enc))\r | |
98 | else:\r | |
99 | tc.LogStdError("Encoding Failure in {0}. Not {1}".format(a, enc))\r | |
100 | overall_status += 1\r | |
101 | \r | |
102 | tc.LogStdOut("Tested Encoding on {0} files".format(files_tested))\r | |
61364ab9 | 103 | if overall_status != 0:\r |
9da7846c SB |
104 | tc.SetFailed("CharEncoding {0} Failed. Errors {1}".format(packagename, overall_status), "CHAR_ENCODING_CHECK_FAILED")\r |
105 | else:\r | |
106 | tc.SetSuccess()\r | |
107 | return overall_status\r | |
108 | \r | |
109 | def TestEncodingOk(self, apath, encodingValue):\r | |
110 | try:\r | |
111 | with open(apath, "rb") as fobj:\r | |
112 | fobj.read().decode(encodingValue)\r | |
113 | except Exception as exp:\r | |
114 | logging.error("Encoding failure: file: {0} type: {1}".format(apath, encodingValue))\r | |
115 | logging.debug("EXCEPTION: while processing {1} - {0}".format(exp, apath))\r | |
116 | return False\r | |
117 | \r | |
118 | return True\r |