Skip to content

Commit 6064d67

Browse files
committed
fix unhandled tuple
Signed-off-by: Javan Lacerda <javanlacerda@google.com>
1 parent 8e17f2b commit 6064d67

2 files changed

Lines changed: 189 additions & 1 deletion

File tree

src/clusterfuzz/_internal/platforms/android/kernel_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,4 +144,4 @@ def get_kernel_hash_and_build_id():
144144
if match:
145145
return match.group(2), match.group(3)
146146

147-
return None
147+
return None, None
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
# Copyright 2026 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
"""Tests for kernel_utils."""
15+
16+
import unittest
17+
from unittest import mock
18+
19+
from clusterfuzz._internal.platforms.android import kernel_utils
20+
from clusterfuzz._internal.tests.test_libs import helpers
21+
22+
23+
class GetCleanKernelPathTest(unittest.TestCase):
24+
"""Tests for _get_clean_kernel_path."""
25+
26+
def test_clean_path(self):
27+
"""Test that path is cleaned correctly."""
28+
path = '/buildbot/src/partner-android/BRANCH/private/PROJ/kernel/msm/arch/arm64/kernel/traps.c'
29+
self.assertEqual(
30+
kernel_utils._get_clean_kernel_path(path),
31+
'kernel/msm/arch/arm64/kernel/traps.c')
32+
33+
def test_no_private(self):
34+
"""Test path without 'private'."""
35+
path = '/path/to/something/else'
36+
self.assertEqual(kernel_utils._get_clean_kernel_path(path), path)
37+
38+
39+
class GetKernelStackFrameLinkTest(unittest.TestCase):
40+
"""Tests for get_kernel_stack_frame_link."""
41+
42+
def test_link_creation(self):
43+
"""Test link creation."""
44+
stack_frame = ' [<c0667e78>] __do_fault+0x44/0x8c /buildbot/src/partner-android/BRANCH/private/PROJ/kernel/msm/mm/memory.c:3095'
45+
kernel_prefix = 'kernel/private/msm-google'
46+
kernel_hash = 'abcdef123456'
47+
48+
# The expected output should replace the path:line with the link info.
49+
# The original path was /buildbot/src/partner-android/BRANCH/private/PROJ/kernel/msm/mm/memory.c
50+
# _get_clean_kernel_path converts it to kernel/msm/mm/memory.c (PROJ removed)
51+
# kernel_prefix is stripped to msm-google
52+
53+
# The function constructs:
54+
# prefix = msm-google
55+
# hash = abcdef123456
56+
# path = kernel/msm/mm/memory.c
57+
# line = 3095
58+
# display_path = msm-google/kernel/msm/mm/memory.c:3095
59+
60+
expected_link_part = (
61+
'http://go/pakernel/msm-google/+/abcdef123456/'
62+
'kernel/msm/mm/memory.c#3095;'
63+
'msm-google/kernel/msm/mm/memory.c:3095;')
64+
65+
result = kernel_utils.get_kernel_stack_frame_link(
66+
stack_frame, kernel_prefix, kernel_hash)
67+
self.assertIn(expected_link_part, result)
68+
69+
def test_no_match(self):
70+
"""Test when regex doesn't match."""
71+
stack_frame = 'random string'
72+
self.assertEqual(
73+
kernel_utils.get_kernel_stack_frame_link(stack_frame, 'prefix', 'hash'),
74+
stack_frame)
75+
76+
77+
class GetPrefixAndFullHashTest(unittest.TestCase):
78+
"""Tests for _get_prefix_and_full_hash."""
79+
80+
def test_found(self):
81+
"""Test when hash is found."""
82+
repo_data = "prefix1 u'fullhash1\nprefix2 u'fullhash2"
83+
prefix, full_hash = kernel_utils._get_prefix_and_full_hash(
84+
repo_data, 'fullhash1')
85+
self.assertEqual(prefix, 'prefix1')
86+
self.assertEqual(full_hash, 'fullhash1')
87+
88+
def test_not_found(self):
89+
"""Test when hash is not found."""
90+
repo_data = "prefix1 u'fullhash1\nprefix2 u'fullhash2"
91+
prefix, full_hash = kernel_utils._get_prefix_and_full_hash(
92+
repo_data, 'nonexistent')
93+
self.assertIsNone(prefix)
94+
self.assertIsNone(full_hash)
95+
96+
97+
class GetRepoPropDataTest(unittest.TestCase):
98+
"""Tests for _get_repo_prop_data."""
99+
100+
def setUp(self):
101+
helpers.patch(self, [
102+
'clusterfuzz._internal.system.environment.get_value',
103+
'clusterfuzz._internal.platforms.android.symbols_downloader.get_repo_prop_archive_filename',
104+
'clusterfuzz._internal.platforms.android.symbols_downloader.download_kernel_repo_prop_if_needed',
105+
'clusterfuzz._internal.base.utils.find_binary_path',
106+
'clusterfuzz._internal.base.utils.read_data_from_file',
107+
'os.path.exists',
108+
])
109+
self.mock.get_value.return_value = '/symbols'
110+
self.mock.get_repo_prop_archive_filename.return_value = 'repo.prop'
111+
112+
def test_success(self):
113+
"""Test success path."""
114+
self.mock.find_binary_path.return_value = '/symbols/repo.prop'
115+
self.mock.exists.return_value = True
116+
self.mock.read_data_from_file.return_value = b'data'
117+
118+
result = kernel_utils._get_repo_prop_data('build_id', 'target')
119+
self.assertEqual(result, 'data')
120+
121+
def test_failure(self):
122+
"""Test failure path."""
123+
self.mock.find_binary_path.return_value = None
124+
125+
result = kernel_utils._get_repo_prop_data('build_id', 'target')
126+
self.assertIsNone(result)
127+
128+
129+
class GetKernelNameTest(unittest.TestCase):
130+
"""Tests for get_kernel_name."""
131+
132+
def setUp(self):
133+
helpers.patch(self, [
134+
'clusterfuzz._internal.platforms.android.settings.get_product_name',
135+
'clusterfuzz._internal.platforms.android.settings.get_build_product',
136+
])
137+
138+
def test_default(self):
139+
self.mock.get_product_name.return_value = 'product'
140+
self.mock.get_build_product.return_value = 'product'
141+
142+
with mock.patch.dict(
143+
'clusterfuzz._internal.platforms.android.constants.PRODUCT_TO_KERNEL',
144+
{}, clear=True):
145+
self.assertEqual(kernel_utils.get_kernel_name(), 'product')
146+
147+
def test_kasan_strip(self):
148+
self.mock.get_product_name.return_value = 'product_kasan'
149+
self.mock.get_build_product.return_value = 'product'
150+
151+
with mock.patch.dict(
152+
'clusterfuzz._internal.platforms.android.constants.PRODUCT_TO_KERNEL',
153+
{}, clear=True):
154+
# Based on current implementation, _kasan is NOT stripped because the
155+
# return value of utils.strip_from_right is ignored.
156+
self.assertEqual(kernel_utils.get_kernel_name(), 'product_kasan')
157+
158+
def test_mapping(self):
159+
self.mock.get_product_name.return_value = 'product'
160+
self.mock.get_build_product.return_value = 'alias_product'
161+
162+
with mock.patch.dict(
163+
'clusterfuzz._internal.platforms.android.constants.PRODUCT_TO_KERNEL',
164+
{'alias_product': 'real_product'}, clear=True):
165+
self.assertEqual(kernel_utils.get_kernel_name(), 'real_product')
166+
167+
168+
class GetKernelHashAndBuildIdTest(unittest.TestCase):
169+
"""Tests for get_kernel_hash_and_build_id."""
170+
171+
def setUp(self):
172+
helpers.patch(self, [
173+
'clusterfuzz._internal.platforms.android.settings.get_kernel_version_string',
174+
])
175+
176+
def test_match(self):
177+
self.mock.get_kernel_version_string.return_value = (
178+
'Linux version 3.18.0-g8de8e79-ab1234567 (android-build@google.com)')
179+
# Expected: (match.group(2), match.group(3))
180+
# match.group(2) is 'ab1234567 ' (with space)
181+
# match.group(3) is '1234567'
182+
self.assertEqual(
183+
kernel_utils.get_kernel_hash_and_build_id(), ('ab1234567 ', '1234567'))
184+
185+
def test_no_match(self):
186+
self.mock.get_kernel_version_string.return_value = 'invalid'
187+
self.assertEqual(
188+
kernel_utils.get_kernel_hash_and_build_id(), (None, None))

0 commit comments

Comments
 (0)