Repository: secdev/scapy

Issue:
UTscapy LaTeX output support is broken
### Brief description

When selecting `-f LaTeX` while running UTscapy tests I got the following error:

```
Traceback (most recent call last):
  File "/usr/lib/python3.9/runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/usr/lib/python3.9/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/home/t/.tox/py39-linux_root/lib/python3.9/site-packages/scapy/tools/UTscapy.py", line 1227, in <module>
    sys.exit(main())
  File "/home/t/.tox/py39-linux_root/lib/python3.9/site-packages/scapy/tools/UTscapy.py", line 1156, in main
    output, result, campaign = execute_campaign(
  File "/home/t/.tox/py39-linux_root/lib/python3.9/site-packages/scapy/tools/UTscapy.py", line 921, in execute_campaign
    output = campaign_to_LATEX(test_campaign)
  File "/home/t/.tox/py39-linux_root/lib/python3.9/site-packages/scapy/tools/UTscapy.py", line 799, in campaign_to_LATEX
    output %= info_line(test_campaign)
TypeError: info_line() missing 1 required positional argument: 'theme'

```
Note: the campaign itself works fine (tests pass/fail as usual) - only the LaTeX output generation is borked, the ansi option works fine for example.

### Scapy version

2.4.5

### Python version

3.9

### Operating system

Ubuntu 21.04

### Additional environment information

I'm using tox to run UTscapy in isolated environment.

### How to reproduce

Run some *.uts with LaTeX output.

### Actual result

Exit code 1.

### Expected result

.tex files are generated.

### Related resources

_No response_


Discussion:
When I look at the code I fail to understand how was it working at all. It seems something like `latex_info_line()` should be used instead of default `info_line()` - similar to `html_info_line()`

Has anyone managed to produce LaTeX output?

Resolving patch:
diff --git a/scapy/themes.py b/scapy/themes.py
--- a/scapy/themes.py
+++ b/scapy/themes.py
@@ -301,7 +301,7 @@ class LatexTheme2(FormatTheme):
     style_packetlist_proto = r"@`@textcolor@[@blue@]@@[@%s@]@"
     style_packetlist_value = r"@`@textcolor@[@purple@]@@[@%s@]@"
     style_fail = r"@`@textcolor@[@red@]@@[@@`@bfseries@[@@]@%s@]@"
-    style_success = r"@`@textcolor@[@blue@]@@[@@`@bfserices@[@@]@%s@]@"
+    style_success = r"@`@textcolor@[@blue@]@@[@@`@bfseries@[@@]@%s@]@"
     style_even = r"@`@textcolor@[@gray@]@@[@@`@bfseries@[@@]@%s@]@"
 #    style_odd = r"@`@textcolor@[@black@]@@[@@`@bfseries@[@@]@%s@]@"
     style_left = r"@`@textcolor@[@blue@]@@[@%s@]@"
diff --git a/scapy/tools/UTscapy.py b/scapy/tools/UTscapy.py
--- a/scapy/tools/UTscapy.py
+++ b/scapy/tools/UTscapy.py
@@ -33,6 +33,7 @@
 from scapy.config import conf
 from scapy.compat import base64_bytes, bytes_hex, plain_str
 from scapy.themes import DefaultTheme, BlackAndWhite
+from scapy.utils import tex_escape
 
 
 # Check UTF-8 support #
@@ -663,6 +664,14 @@ def html_info_line(test_campaign):
         return """Run %s from [%s] by <a href="http://www.secdev.org/projects/UTscapy/">UTscapy</a><br>""" % (time.ctime(), filename)  # noqa: E501
 
 
+def latex_info_line(test_campaign):
+    filename = test_campaign.filename
+    if filename is None:
+        return """by UTscapy""", """%s""" % time.ctime()
+    else:
+        return """from %s by UTscapy""" % tex_escape(filename), """%s""" % time.ctime()
+
+
 #    CAMPAIGN TO something    #
 
 def campaign_to_TEXT(test_campaign, theme):
@@ -792,19 +801,9 @@ def pack_html_campaigns(runned_campaigns, data, local=False, title=None):
 
 
 def campaign_to_LATEX(test_campaign):
-    output = r"""\documentclass{report}
-\usepackage{alltt}
-\usepackage{xcolor}
-\usepackage{a4wide}
-\usepackage{hyperref}
-
-\title{%(title)s}
-\date{%%s}
-
-\begin{document}
-\maketitle
-\tableofcontents
-
+    output = r"""
+\chapter{%(title)s}
+Run %%s on \date{%%s}
 \begin{description}
 \item[Passed:] %(passed)i
 \item[Failed:] %(failed)i
@@ -813,15 +812,16 @@ def campaign_to_LATEX(test_campaign):
 %(headcomments)s
 
 """ % test_campaign
-    output %= info_line(test_campaign)
+    output %= latex_info_line(test_campaign)
 
     for testset in test_campaign:
-        output += "\\chapter{%(name)s}\n\n%(comments)s\n\n" % testset
+        output += "\\section{%(name)s}\n\n%(comments)s\n\n" % testset
         for t in testset:
+            t.comments = tex_escape(t.comments)
             if t.expand:
-                output += r"""\section{%(name)s}
+                output += r"""\subsection{%(name)s}
 
-[%(num)03i] [%(result)s]
+Test result: \textbf{%(result)s}\newline
 
 %(comments)s
 \begin{alltt}
@@ -830,7 +830,30 @@ def campaign_to_LATEX(test_campaign):
 
 """ % t
 
-    output += "\\end{document}\n"
+    return output
+
+
+def pack_latex_campaigns(runned_campaigns, data, local=False, title=None):
+    output = r"""
+\documentclass{report}
+\usepackage{alltt}
+\usepackage{xcolor}
+\usepackage{a4wide}
+\usepackage{hyperref}
+
+\title{%(title)s}
+
+\begin{document}
+\maketitle
+\tableofcontents
+
+%(data)s
+\end{document}\n
+"""
+
+    out_dict = {'data': data, 'title': title if title else "UTScapy tests"}
+
+    output %= out_dict
     return output
 
 
@@ -1197,6 +1220,8 @@ def main():
     # Concenate outputs
     if FORMAT == Format.HTML:
         glob_output = pack_html_campaigns(runned_campaigns, glob_output, LOCAL, glob_title)
+    if FORMAT == Format.LATEX:
+        glob_output = pack_latex_campaigns(runned_campaigns, glob_output, LOCAL, glob_title)
 
     # Write the final output
     # Note: on Python 2, we force-encode to ignore ascii errors


Test patch: