diff --git a/sentry/README.rst b/sentry/README.rst
index 8728a5624d8..2297e12ebcd 100644
--- a/sentry/README.rst
+++ b/sentry/README.rst
@@ -7,7 +7,7 @@ Sentry
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- !! source digest: sha256:88c5722f68e393e581f3bd3dfc08a4350731602583fdce2d407f6efcede43443
+ !! source digest: sha256:fb1e0787f353def76b80f3aae5948d0b7a9b01d35f2f738a5b96fa28588bab0e
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
diff --git a/sentry/i18n/sentry.pot b/sentry/i18n/sentry.pot
index 78d58d53fe0..716a0702d88 100644
--- a/sentry/i18n/sentry.pot
+++ b/sentry/i18n/sentry.pot
@@ -3,7 +3,7 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: Odoo Server 16.0\n"
+"Project-Id-Version: Odoo Server 17.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: \n"
"Language-Team: \n"
diff --git a/sentry/static/description/index.html b/sentry/static/description/index.html
index 25178af786d..6046c9bfa4d 100644
--- a/sentry/static/description/index.html
+++ b/sentry/static/description/index.html
@@ -366,7 +366,7 @@
Sentry
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-!! source digest: sha256:88c5722f68e393e581f3bd3dfc08a4350731602583fdce2d407f6efcede43443
+!! source digest: sha256:fb1e0787f353def76b80f3aae5948d0b7a9b01d35f2f738a5b96fa28588bab0e
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

This module allows painless Sentry integration
diff --git a/sentry/tests/__init__.py b/sentry/tests/__init__.py
index 21926387ae5..184488f04bf 100644
--- a/sentry/tests/__init__.py
+++ b/sentry/tests/__init__.py
@@ -1,4 +1,4 @@
# Copyright 2016-2017 Versada
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-from . import test_client, test_logutils
+from . import test_client, test_logutils, test_processor, test_generalutils
diff --git a/sentry/tests/test_generalutils.py b/sentry/tests/test_generalutils.py
new file mode 100644
index 00000000000..8d986721932
--- /dev/null
+++ b/sentry/tests/test_generalutils.py
@@ -0,0 +1,48 @@
+import typing
+from collections import namedtuple
+
+from odoo.tests import TransactionCase
+
+from .. import generalutils
+
+
+class TestGeneralUtils(TransactionCase):
+ def test_is_namedtuple(self):
+ self.assertFalse(generalutils.is_namedtuple(["a list"]))
+ self.assertFalse(generalutils.is_namedtuple(("a normal tuple",)))
+ a_namedtuple = namedtuple("a_namedtuple", ["some_string"])
+ self.assertTrue(generalutils.is_namedtuple(a_namedtuple("a namedtuple")))
+
+ class AnotherNamedtuple(typing.NamedTuple):
+ some_string: str
+
+ self.assertTrue(
+ generalutils.is_namedtuple(AnotherNamedtuple("a subclassed namedtuple"))
+ )
+
+ def test_varmap(self):
+ top = {
+ "middle": [
+ "a list",
+ "that contains",
+ "the outer dict",
+ ],
+ }
+ top["middle"].append(top)
+
+ def func(_, two):
+ return two
+
+ # Don't care about the result, just that we don't get a recursion error
+ generalutils.varmap(func, top)
+
+ def test_get_environ(self):
+ fake_environ = {
+ "REMOTE_ADDR": None,
+ "SERVER_PORT": None,
+ "FORBIDDEN_VAR": None,
+ }
+ self.assertEqual(
+ ["REMOTE_ADDR", "SERVER_PORT"],
+ list(key for key, _ in generalutils.get_environ(fake_environ)),
+ )
diff --git a/sentry/tests/test_logutils.py b/sentry/tests/test_logutils.py
index 256f647be49..6785e9e2cc9 100644
--- a/sentry/tests/test_logutils.py
+++ b/sentry/tests/test_logutils.py
@@ -1,9 +1,10 @@
# Copyright 2016-2017 Versada
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+import os
from odoo.tests import TransactionCase
-from ..logutils import SanitizeOdooCookiesProcessor
+from .. import logutils
class TestOdooCookieSanitizer(TransactionCase):
@@ -17,7 +18,7 @@ def test_cookie_as_string(self):
}
}
- proc = SanitizeOdooCookiesProcessor()
+ proc = logutils.SanitizeOdooCookiesProcessor()
result = proc.process(data)
self.assertTrue("request" in result)
@@ -33,7 +34,7 @@ def test_cookie_as_string(self):
def test_cookie_as_string_with_partials(self):
data = {"request": {"cookies": "website_lang=en_us;session_id;foo=bar"}}
- proc = SanitizeOdooCookiesProcessor()
+ proc = logutils.SanitizeOdooCookiesProcessor()
result = proc.process(data)
self.assertTrue("request" in result)
@@ -55,7 +56,7 @@ def test_cookie_header(self):
}
}
- proc = SanitizeOdooCookiesProcessor()
+ proc = logutils.SanitizeOdooCookiesProcessor()
result = proc.process(data)
self.assertTrue("request" in result)
@@ -67,3 +68,8 @@ def test_cookie_header(self):
f"Session_ID={proc.MASK};"
f"a_session_id_here={proc.MASK}",
)
+
+ def test_git_sha_failure(self):
+ with self.assertRaises(logutils.InvalidGitRepository):
+ # Assume this test file is not in the repo root
+ logutils.fetch_git_sha(os.path.dirname(__file__))
diff --git a/sentry/tests/test_processor.py b/sentry/tests/test_processor.py
new file mode 100644
index 00000000000..fffed9c4b1f
--- /dev/null
+++ b/sentry/tests/test_processor.py
@@ -0,0 +1,48 @@
+from odoo.tests import TransactionCase
+
+from .. import processor
+
+
+class TestSanitizers(TransactionCase):
+ def test_sanitize_password(self):
+ sanitizer = processor.SanitizePasswordsProcessor()
+ for password in [
+ "1234-5678-9012-3456",
+ "1234 5678 9012 3456",
+ "1234 - 5678- -0987---1234",
+ "123456789012345",
+ ]:
+ with self.subTest(
+ password=password,
+ msg="password should have been sanitized",
+ ):
+ self.assertEqual(
+ sanitizer.sanitize(None, password),
+ sanitizer.MASK,
+ )
+ for not_password in [
+ "1234",
+ "hello",
+ "text long enough",
+ "numbers and 73X7",
+ "12345678901234567890",
+ b"12345678901234567890",
+ b"1234 5678 9012 3456",
+ "1234-5678-9012-3456-7890",
+ ]:
+ with self.subTest(
+ not_password=password,
+ msg="not_password should not have been sanitized",
+ ):
+ self.assertEqual(
+ sanitizer.sanitize(None, not_password),
+ not_password,
+ )
+
+ def test_sanitize_keys(self):
+ sanitizer = processor.SanitizeKeysProcessor()
+ self.assertIsNone(sanitizer.sanitize_keys)
+
+ def test_sanitize_none(self):
+ sanitizer = processor.SanitizePasswordsProcessor()
+ self.assertIsNone(sanitizer.sanitize(None, None))