Makoto Itoh

122 papers B 25C 4Journal 54Unranked 36
YearRankTypeTitle / Venue / Authors
2026 J jnl
CoRR
Truong Thanh Hung Nguyen, Hélène Fournier, Piper J. Jackson, Makoto Itoh, Shannon Freeman, Rene Richard, Hung Cao
2025 conf
ICNSC
Chokiu Leung, Yingzhi Zhang, Hitesh Pandya, Tiago Rodrigues, Makoto Itoh
2025 J jnl
CoRR
Carlos Andrés Ramírez Cataño, Makoto Itoh
2025 J jnl
CoRR
Keisuke Fujii, Kazushi Tsutsui, Yu Teshima, Makoto Itoh, Naoya Takeishi, Nozomi Nishiumi, Ryoya Tanaka, Shunsuke Shigaki, Yoshinobu Kawahara
2025 B conf
SMC
Yuichi Saito, Shota Yano, Makoto Itoh
2025 conf
HCI (53)
Zixin Cui, Nianzhi Tu, Jieun Lee, Makoto Itoh
2024 J jnl
CoRR
Zixin Cui, Xiangling Zhuang, Seul Chan Lee, Jieun Lee, Xintong Li, Makoto Itoh
2024 conf
GCCE
Nianzhi Tu, Zixin Cui, Makoto Itoh
2024 conf
ICHMS
Yichen Dong, Andrijanto, Hiroaki Yano, Makoto Itoh
2024 J jnl
IEEE Trans. Intell. Veh.
Andika Aji Wijaya, Fitri Yakub, Shahrum Shah Abdullah, Rini Akmeliawati, Salem M. Aljazzar, Makoto Itoh
2023 conf
SUI
Shota Imamura, Jieun Lee, Jun Rekimoto, Makoto Itoh
2023 B conf
ETRA
Shota Imamura, Jieun Lee, Makoto Itoh
2023 conf
DSA
Jingjing Li, Kai Sheng, Lei Ao, Makoto Itoh, Qinghai Yang
2023 conf
SICE
Nianzhi Tu, Sungju Maeng, Makoto Itoh
2022 conf
VR Workshops
Andrijanto, Zhangyijing Chen, Takuro Kodama, Hiroaki Yano, Makoto Itoh
2022 J jnl
IEEE Trans. Hum. Mach. Syst.
Yuichi Saito, Makoto Itoh, Toshiyuki Inagaki
2022 conf
TALE
Maki Arame, Junko Handa, Yoshiko Goda, Masashi Toda, Makoto Itoh, Satoshi Kitazaki
2022 conf
AutomotiveUI (Adjunct Proceedings)
Rattawut Vongvit, Jieun Lee, Makoto Itoh, Seul Chan Lee
2022 conf
SICE
Takatomo Watanabe, Makoto Itoh
2021 B conf
SMC
Yuichi Saito, Husam Muslim, Makoto Itoh
2021 J jnl
IEEE Trans. Hum. Mach. Syst.
Huiping Zhou, Makoto Itoh, Satoshi Kitazaki
2021 J jnl
Hum. Factors
Husam Muslim, Makoto Itoh
2021 conf
ICICT (3)
Maki Arame, Junko Handa, Yoshiko Goda, Masashi Toda, Ryuichi Matsuba, Huiping Zhou, Makoto Itoh, Satoshi Kitazaki
2020 conf
ICHMS
Frank Ole Flemisch, Marie-Pierre Pacaux-Lemoine, Frédéric Vanderhaegen, Makoto Itoh, Yuichi Saito, Nicolas Daniel Herzberger, Joscha Wasser, Emmanuelle Grislin, Marcel Baltzer
2020 conf
TALE
Yoshiko Goda, Maki Arame, Junko Handa, Masashi Toda, Ryuichi Matsuba, Huiping Zhou, Makoto Itoh, Satoshi Kitazaki
2020 J jnl
Cogn. Technol. Work.
Huiping Zhou, Makoto Itoh, Satoshi Kitazaki
2020 B conf
SMC
Husam Muslim, Cho Kiu Liang, Makoto Itoh
2020 J jnl
J. Robotics Mechatronics
Jieun Lee, Genya Abe, Kenji Sato, Makoto Itoh
2020 conf
ICHMS
Yuichi Saito, Makoto Itoh, Toshiyuki Inagaki
2020 conf
SICE
Hua Yao, Suyang An, Huiping Zhou, Makoto Itoh
2020 J jnl
Hum. Factors
Yusuke Yamani, Shelby K. Long, Makoto Itoh
2020 conf
ICHMS
Jieun Lee, Genya Abe, Kenji Sato, Makoto Itoh
2020 B conf
SMC
Jieun Lee, Toshiaki Hirano, Makoto Itoh
2020 J jnl
J. Robotics Mechatronics
Hua Yao, Suyang An, Huiping Zhou, Makoto Itoh
2019 J jnl
J. Robotics Mechatronics
Hiroshi Takahashi, Makoto Itoh
2019 J jnl
Cogn. Technol. Work.
Husam Muslim, Makoto Itoh
2019 B conf
SMC
Jieun Lee, Toshiaki Hirano, Tomoya Hano, Makoto Itoh
2019 J jnl
IEEE Trans. Intell. Transp. Syst.
Husam Muslim, Makoto Itoh
2019 conf
GCCE
Husam Muslim, Makoto Itoh
2019 J jnl
Cogn. Technol. Work.
Frank Flemisch, David A. Abbink, Makoto Itoh, Marie-Pierre Pacaux-Lemoine, Gina Weßel
2019 B conf
SMC
Huiping Zhou, Makoto Itoh, Satoshi Kitazaki
2019 ch.
Handbook of Memristor Networks
Makoto Itoh, Leon O. Chua
2019 J jnl
CoRR
Makoto Itoh
2019 J jnl
Cogn. Technol. Work.
Frank Flemisch, David A. Abbink, Makoto Itoh, Marie-Pierre Pacaux-Lemoine
2019 J jnl
Cogn. Technol. Work.
Natasha Merat, Bobbie Seppelt, Tyron Louw, Johan Engström, John D. Lee, Emma Johansson, Charles A. Green, Satoshi Katazaki, Chris Monk, Makoto Itoh, Daniel V. McGehee, Takashi Sunda, Kiyozumi Unoura, Trent Victor, Anna Schieben, Andreas Keinath
2018 conf
SCIS&ISIS
Hiroshi Takahashi, Makoto Itoh
2018 J jnl
IEEE Trans. Hum. Mach. Syst.
Genya Abe, Kenji Sato, Makoto Itoh
2018 B conf
SMC
Makoto Itoh, Huiping Zhou, Satoshi Kitazaki
2018 B conf
SMC
Husam Muslim, Makoto Itoh
2018 B conf
Intelligent Vehicles Symposium
Tianwei Liu, Huiping Zhou, Makoto Itoh, Satoshi Kitazaki
2018 B conf
SMC
Makoto Itoh, Marie-Pierre Pacaux-Lemoine
2018 conf
ICPS
Makoto Itoh, Huiping Zhou, Satoshi Kitazaki
2017 J jnl
Int. J. Bifurc. Chaos
Makoto Itoh, Leon O. Chua
2017 B conf
SMC
Jieun Lee, Makoto Itoh
2017 J jnl
Int. J. Bifurc. Chaos
Makoto Itoh, Leon O. Chua
2017 B conf
SMC
Wakana Ishida, Makoto Itoh
2017 B conf
SMC
Frank Flemisch, Yigiterkut Canpolat, Eugen Altendorf, Gina Weßel, Makoto Itoh, Marcel Baltzer, Marie-Pierre Pacaux-Lemoine, David A. Abbink, Paul Schutte
2017 B conf
SMC
Husam Muslim, Makoto Itoh
2016 J jnl
IEEE Trans. Hum. Mach. Syst.
Yuichi Saito, Makoto Itoh, Toshiyuki Inagaki
2016 B conf
SMC
Husam Muslim, Makoto Itoh, Marie-Pierre Pacaux-Lemoine
2016 J jnl
Int. J. Bifurc. Chaos
Makoto Itoh, Leon O. Chua
2016 B conf
SMC
Takuya Aizawa, Makoto Itoh
2015 conf
HCI (5)
Ahmad Khushairy Makhtar, Makoto Itoh
2015 B conf
SMC
Genya Abe, Kenji Sato, Makoto Itoh
2015 conf
HCI (5)
Tasuku Sotokawa, Takuya Murayama, Junko Noguchi, Yoko Sakimura, Makoto Itoh
2015 conf
HCI (5)
Huiping Zhou, Makoto Itoh
2015 C conf
IECON
Jieun Lee, Makoto Itoh, Toshiyuki Inagaki
2015 J jnl
Interact. Comput.
Sandrine Fischer, Makoto Itoh, Toshiyuki Inagaki
2015 J jnl
J. Hum. Robot Interact.
Makoto Itoh, Hiroto Tanaka, Toshiyuki Inagaki
2015 B conf
SMC
Marie-Pierre Pacaux-Lemoine, Makoto Itoh
2015 conf
HCI (4)
Sandrine Fischer, Blaine Oelkers, Mitchell Fierro, Makoto Itoh, Eric White
2014 B conf
SMC
Yuichi Saito, Makoto Itoh, Toshiyuki Inagaki
2014 J jnl
Int. J. Bifurc. Chaos
Makoto Itoh, Leon O. Chua
2014 J jnl
Cogn. Technol. Work.
Makoto Itoh, Genya Abe, Tomohiro Yamamura
2013 conf
HCI (14)
Makoto Itoh, Masashi Kawase, Keita Matsuzaki, Katsumi Yamamoto, Shin'ichi Yokoyama, Masaaki Okada
2013 J jnl
Int. J. Bifurc. Chaos
Makoto Itoh, Leon O. Chua
2013 B conf
Intelligent Vehicles Symposium
Junpei Kuwana, Makoto Itoh, Toshiyuki Inagaki
2013 conf
HCI (14)
Yuichi Saito, Shin Kato, Makoto Itoh, Toshiyuki Inagaki
2012 B conf
SMC
Makoto Itoh, Toshiyuki Inagaki, Hiroto Tanaka
2012 J jnl
Cogn. Technol. Work.
Makoto Itoh
2011 B conf
SMC
Makoto Itoh, Toshiyuki Inagaki, Tatsuya Horikome
2011 J jnl
Int. J. Bifurc. Chaos
Makoto Itoh, Leon O. Chua
2010 J jnl
Int. J. Bifurc. Chaos
Makoto Itoh, Leon O. Chua
2009 conf
AutomotiveUI
Sandrine Fischer, Makoto Itoh, Toshiyuki Inagaki
2009 J jnl
Int. J. Bifurc. Chaos
Makoto Itoh, Leon O. Chua
2009 conf
ICIRA
Genya Abe, Makoto Itoh, Tomohiro Yamamura
2009 conf
ICIRA
Huiping Zhou, Makoto Itoh, Toshiyuki Inagaki
2009 J jnl
Int. J. Bifurc. Chaos
Makoto Itoh, Leon O. Chua
2009 conf
ICIRA
Makoto Itoh
2008 J jnl
Int. J. Bifurc. Chaos
Makoto Itoh, Leon O. Chua
2008 J jnl
Int. J. Bifurc. Chaos
Makoto Itoh, Leon O. Chua
2007 conf
IFAC HMS
Toshiyuki Inagaki, Makoto Itoh
2007 J jnl
Int. J. Bifurc. Chaos
Makoto Itoh, Leon O. Chua
2007 J jnl
Int. J. Bifurc. Chaos
Makoto Itoh, Leon O. Chua
2007 conf
IFAC HMS
Makoto Itoh, Toshiyuki Inagaki
2007 J jnl
Int. J. Bifurc. Chaos
Makoto Itoh, Leon O. Chua
2007 J jnl
IEICE Trans. Fundam. Electron. Commun. Comput. Sci.
Toshiyuki Inagaki, Makoto Itoh, Yoshitomo Nagai
2006 J jnl
Int. J. Bifurc. Chaos
Makoto Itoh, Leon O. Chua
2005 J jnl
Int. J. Bifurc. Chaos
Makoto Itoh, Leon O. Chua
2005 J jnl
Int. J. Bifurc. Chaos
Makoto Itoh, Leon O. Chua
2005 conf
CIMCA/IAWTIC
Kenji Tanaka, Yo Ishigaki, Hiroyulu Inoue, Makoto Itoh
2004 J jnl
Int. J. Hum. Comput. Interact.
Makoto Itoh, Toshiyuki Inagaki
2004 J jnl
Int. J. Bifurc. Chaos
Makoto Itoh, Leon O. Chua
2004 J jnl
Int. J. Bifurc. Chaos
Makoto Itoh, Leon O. Chua
2004 J jnl
Int. J. Bifurc. Chaos
Makoto Itoh, Leon O. Chua
2003 J jnl
Int. J. Bifurc. Chaos
Makoto Itoh, Leon O. Chua
2003 J jnl
Int. J. Bifurc. Chaos
Makoto Itoh, Leon O. Chua
2002 J jnl
Int. J. Bifurc. Chaos
Makoto Itoh, Leon O. Chua
2001 J jnl
Int. J. Bifurc. Chaos
Makoto Itoh, Tao Yang, Leon O. Chua
2001 conf
VTC Fall
Toshiyuki Futakata, Makoto Itoh, Sung Uk Moon, Shinji Uebayashi
2001 J jnl
Int. J. Bifurc. Chaos
Makoto Itoh, Pedro Julián, Leon O. Chua
2001 J jnl
Int. J. Bifurc. Chaos
Makoto Itoh
2000 B conf
SMC
Makoto Itoh, Daisuke Sakami, Kenji Tanaka
2000 B conf
SMC
Kenji Tanaka, Makoto Itoh
1999 conf
ISCAS (5)
Makoto Itoh
1997 conf
SCAI
Makoto Itoh, Toshiyuki Inagaki
1995 C conf
ISCAS
Makoto Itoh, Hiroyuki Murakami, Leon O. Chua
1994 C conf
ISCAS
Makoto Itoh, Hiroyuki Murakami, Leon O. Chua
1994 C conf
ISCAS
Makoto Itoh, Hiroyuki Murakami, Leon O. Chua
1993 ch.
Chua's Circuit
Leon O. Chua, Makoto Itoh, Ljupco Kocarev, Kevin Eckert
1993 J jnl
J. Circuits Syst. Comput.
Leon O. Chua, Makoto Itoh, Ljupco Kocarev, Kevin Eckert
1993 ch.
Chua's Circuit
K. Sean Halle, Chai-Wah Wu, Makoto Itoh, Leon O. Chua
tests/unit/test_apk_dataclasses.py
← Index tests/unit/test_apk_dataclasses.py python
"""
Unit tests for APK dataclasses in redb/models/dataclasses.py.
"""
import pytest
from dataclasses import asdict, fields

pytestmark = [pytest.mark.unit, pytest.mark.dataclass, pytest.mark.apk]


# ============================================================================
# APKFeatures
# ============================================================================

class TestAPKFeaturesDataclass:
    """Tests for APKFeatures dataclass."""

    def test_named_fields(self):
        from redb.models.dataclasses import APKFeatures

        f = APKFeatures(
            package_name="com.example.app",
            app_name="Example App",
            version_code=1,
            version_name="1.0.0",
        )
        assert f.package_name == "com.example.app"
        assert f.app_name == "Example App"
        assert f.version_code == 1
        assert f.version_name == "1.0.0"

    def test_all_fields_default_none_or_safe(self):
        from redb.models.dataclasses import APKFeatures

        f = APKFeatures()
        # Nullable fields default to None
        assert f.package_name is None
        assert f.app_name is None
        assert f.version_code is None
        assert f.version_name is None
        assert f.min_sdk_version is None
        assert f.target_sdk_version is None
        assert f.compile_sdk_version is None
        assert f.main_activity is None
        # Non-nullable fields have safe defaults
        assert f.is_debuggable is False
        assert f.allow_backup is True
        assert f.uses_cleartext_traffic is False
        assert f.supported_abis == []
        assert f.dex_count == 0
        assert f.total_dex_size == 0
        assert f.total_file_count == 0
        assert f.has_native_code is False
        assert f.has_assets is False
        assert f.uses_libraries == []
        assert f.earliest_content_modification is None
        assert f.latest_content_modification is None
        assert f.contains_embedded_apk is False

    def test_all_fields_populated(self):
        from redb.models.dataclasses import APKFeatures

        f = APKFeatures(
            package_name="com.malware.test",
            app_name="Malware",
            version_code=42,
            version_name="6.6.6",
            min_sdk_version=21,
            target_sdk_version=33,
            compile_sdk_version=33,
            main_activity="com.malware.test.MainActivity",
            is_debuggable=True,
            allow_backup=False,
            uses_cleartext_traffic=True,
            supported_abis=["armeabi-v7a", "arm64-v8a", "x86"],
            dex_count=3,
            total_dex_size=5000000,
            total_file_count=200,
            has_native_code=True,
            has_assets=True,
            uses_libraries=["com.google.android.maps"],
            earliest_content_modification="2024-01-01T00:00:00Z",
            latest_content_modification="2024-06-15T12:00:00Z",
            contains_embedded_apk=True,
        )
        assert f.is_debuggable is True
        assert f.dex_count == 3
        assert len(f.supported_abis) == 3
        assert f.contains_embedded_apk is True

    def test_asdict_roundtrip(self):
        from redb.models.dataclasses import APKFeatures

        f = APKFeatures(
            package_name="com.test",
            app_name="Test",
            version_code=1,
            version_name="1.0",
        )
        d = asdict(f)
        assert d["package_name"] == "com.test"
        assert d["is_debuggable"] is False
        assert d["supported_abis"] == []

    def test_partial_extraction(self):
        """Verify that APKFeatures can be created with only some fields populated,
        simulating a partial extraction where some fields failed."""
        from redb.models.dataclasses import APKFeatures

        f = APKFeatures(
            package_name="com.example.app",
            # app_name failed to extract — left as None
            version_code=10,
            # version_name failed to extract — left as None
            is_debuggable=True,
            dex_count=2,
        )
        assert f.package_name == "com.example.app"
        assert f.app_name is None
        assert f.version_code == 10
        assert f.version_name is None
        assert f.is_debuggable is True
        assert f.dex_count == 2


# ============================================================================
# APKManifestComponent
# ============================================================================

class TestAPKManifestComponentDataclass:

    def test_creation(self):
        from redb.models.dataclasses import APKManifestComponent

        c = APKManifestComponent(
            component_type="activity",
            class_name="com.example.MainActivity",
            is_exported=True,
            intent_actions=["android.intent.action.MAIN"],
            intent_categories=["android.intent.category.LAUNCHER"],
        )
        assert c.component_type == "activity"
        assert c.class_name == "com.example.MainActivity"
        assert c.is_exported is True
        assert len(c.intent_actions) == 1
        assert len(c.intent_categories) == 1

    def test_defaults(self):
        from redb.models.dataclasses import APKManifestComponent

        c = APKManifestComponent(
            component_type="service",
            class_name="com.example.MyService",
            is_exported=False,
        )
        assert c.intent_actions == []
        assert c.intent_categories == []


# ============================================================================
# APKManifest
# ============================================================================

class TestAPKManifestDataclass:

    def test_required_fields(self):
        from redb.models.dataclasses import APKManifest

        m = APKManifest(
            activity_count=5,
            service_count=2,
            receiver_count=3,
            provider_count=1,
        )
        assert m.activity_count == 5
        assert m.service_count == 2
        assert m.receiver_count == 3
        assert m.provider_count == 1

    def test_optional_list_defaults(self):
        from redb.models.dataclasses import APKManifest

        m = APKManifest(
            activity_count=0,
            service_count=0,
            receiver_count=0,
            provider_count=0,
        )
        assert m.activities == []
        assert m.services == []
        assert m.receivers == []
        assert m.providers == []
        assert m.exported_components == []
        assert m.intent_filters_by_action == []
        assert m.intent_filters_by_category == []
        assert m.uses_features == []
        assert m.meta_data is None
        assert m.manifest_xml is None

    def test_fully_populated(self):
        from redb.models.dataclasses import APKManifest

        m = APKManifest(
            activity_count=2,
            service_count=1,
            receiver_count=1,
            provider_count=0,
            activities=["MainActivity", "SettingsActivity"],
            services=["SyncService"],
            receivers=["BootReceiver"],
            providers=[],
            exported_components=["MainActivity", "BootReceiver"],
            intent_filters_by_action=["android.intent.action.MAIN"],
            uses_features=["android.hardware.camera"],
            manifest_xml="<manifest>...</manifest>",
        )
        assert len(m.activities) == 2
        assert len(m.exported_components) == 2
        assert m.manifest_xml is not None


# ============================================================================
# APKPermission / APKPermissions
# ============================================================================

class TestAPKPermissionDataclass:

    def test_creation(self):
        from redb.models.dataclasses import APKPermission

        p = APKPermission(
            permission_name="android.permission.CAMERA",
            protection_level="dangerous",
        )
        assert p.permission_name == "android.permission.CAMERA"
        assert p.protection_level == "dangerous"
        assert p.is_custom is False

    def test_custom_permission(self):
        from redb.models.dataclasses import APKPermission

        p = APKPermission(
            permission_name="com.example.CUSTOM_PERM",
            protection_level="signature",
            is_custom=True,
        )
        assert p.is_custom is True


class TestAPKPermissionsDataclass:

    def test_required_fields(self):
        from redb.models.dataclasses import APKPermissions

        p = APKPermissions(
            total_permission_count=10,
            dangerous_permission_count=3,
        )
        assert p.total_permission_count == 10
        assert p.dangerous_permission_count == 3

    def test_defaults(self):
        from redb.models.dataclasses import APKPermissions

        p = APKPermissions(
            total_permission_count=0,
            dangerous_permission_count=0,
        )
        assert p.permissions == []
        assert p.dangerous_permissions == []
        assert p.custom_permissions == []
        assert p.permission_details == []
        assert p.permhash is None

    def test_with_permission_details(self):
        from redb.models.dataclasses import APKPermission, APKPermissions

        details = [
            APKPermission("android.permission.INTERNET", "normal"),
            APKPermission("android.permission.CAMERA", "dangerous"),
        ]
        p = APKPermissions(
            total_permission_count=2,
            dangerous_permission_count=1,
            permissions=["android.permission.INTERNET", "android.permission.CAMERA"],
            dangerous_permissions=["android.permission.CAMERA"],
            permission_details=details,
            permhash="abc123def456",
        )
        assert len(p.permission_details) == 2
        assert p.permhash == "abc123def456"


# ============================================================================
# APKCertificate / APKCodeSigningInfo
# ============================================================================

class TestAPKCertificateDataclass:

    def test_required_fields(self):
        from redb.models.dataclasses import APKCertificate

        c = APKCertificate(
            subject="CN=Android Debug",
            issuer="CN=Android Debug",
            serial_number="1234567890",
            valid_from="2024-01-01",
            valid_to="2054-01-01",
            thumbprint_sha1="aabbccdd" * 5,
            thumbprint_sha256="aabbccdd" * 8,
        )
        assert c.subject == "CN=Android Debug"
        assert c.issuer == "CN=Android Debug"
        assert c.is_self_signed is False

    def test_optional_fields(self):
        from redb.models.dataclasses import APKCertificate

        c = APKCertificate(
            subject="CN=Test",
            issuer="CN=CA",
            serial_number="1",
            valid_from="2024-01-01",
            valid_to="2025-01-01",
            thumbprint_sha1="aa" * 20,
            thumbprint_sha256="bb" * 32,
            algorithm="SHA256withRSA",
            key_size=2048,
            is_self_signed=True,
        )
        assert c.algorithm == "SHA256withRSA"
        assert c.key_size == 2048
        assert c.is_self_signed is True


class TestAPKCodeSigningInfoDataclass:

    def test_required_fields(self):
        from redb.models.dataclasses import APKCodeSigningInfo

        info = APKCodeSigningInfo(
            _id="abcdef1234567890" * 4,
            is_signed=True,
        )
        assert info.is_signed is True
        assert info.signature_scheme_versions == []
        assert info.number_of_certificates == 0
        assert info.x509_certificates is None
        assert info.apk_signer_subject is None
        assert info.apk_signer_issuer is None

    def test_fully_populated(self):
        from redb.models.dataclasses import APKCertificate, APKCodeSigningInfo

        cert = APKCertificate(
            subject="CN=Test",
            issuer="CN=Test",
            serial_number="1",
            valid_from="2024-01-01",
            valid_to="2025-01-01",
            thumbprint_sha1="aa" * 20,
            thumbprint_sha256="bb" * 32,
        )
        info = APKCodeSigningInfo(
            _id="cc" * 32,
            is_signed=True,
            signature_scheme_versions=[1, 2, 3],
            number_of_certificates=1,
            x509_certificates=[cert],
            apk_signer_subject="CN=Test",
            apk_signer_issuer="CN=Test",
        )
        assert len(info.signature_scheme_versions) == 3
        assert info.number_of_certificates == 1
        assert len(info.x509_certificates) == 1


# ============================================================================
# APKDexFile
# ============================================================================

class TestAPKDexFileDataclass:

    def test_required_fields(self):
        from redb.models.dataclasses import APKDexFile

        d = APKDexFile(
            filename="classes.dex",
            sha256="aa" * 32,
            class_count=100,
            method_count=500,
            string_count=1000,
        )
        assert d.filename == "classes.dex"
        assert d.class_count == 100
        assert d.method_count == 500
        assert d.string_count == 1000

    def test_optional_fields_defaults(self):
        from redb.models.dataclasses import APKDexFile

        d = APKDexFile(
            filename="classes2.dex",
            sha256="bb" * 32,
            class_count=0,
            method_count=0,
            string_count=0,
        )
        assert d.tlsh is None
        assert d.top_packages is None
        assert d.api_usage is None
        assert d.obfuscation_indicators is None

    def test_tlsh_populated(self):
        from redb.models.dataclasses import APKDexFile

        tlsh_value = "T1" + "A" * 68
        d = APKDexFile(
            filename="classes.dex",
            sha256="aa" * 32,
            class_count=100,
            method_count=500,
            string_count=1000,
            tlsh=tlsh_value,
        )
        assert d.tlsh == tlsh_value

    def test_with_api_usage(self):
        from redb.models.dataclasses import APKDexFile

        d = APKDexFile(
            filename="classes.dex",
            sha256="cc" * 32,
            class_count=50,
            method_count=200,
            string_count=300,
            top_packages=[{"name": "com.example", "class_count": 30}],
            api_usage={
                "crypto": ["Ljavax/crypto/Cipher;->getInstance"],
                "reflection": ["Ljava/lang/Class;->forName"],
            },
            obfuscation_indicators={"short_class_names_ratio": 0.8, "single_char_methods_ratio": 0.5},
        )
        assert len(d.api_usage) == 2
        assert d.obfuscation_indicators["short_class_names_ratio"] == 0.8


# ============================================================================
# APKResource
# ============================================================================

class TestAPKResourceDataclass:

    def test_creation(self):
        from redb.models.dataclasses import APKResource

        r = APKResource(
            path="res/drawable/icon.png",
            size=1024,
            sha256="dd" * 32,
            filetype_magika="png",
        )
        assert r.path == "res/drawable/icon.png"
        assert r.size == 1024
        assert r.is_suspicious is False

    def test_suspicious_resource(self):
        from redb.models.dataclasses import APKResource

        r = APKResource(
            path="assets/payload.dex",
            size=50000,
            sha256="ee" * 32,
            filetype_magika="dex",
            is_suspicious=True,
        )
        assert r.is_suspicious is True


# ============================================================================
# APKNativeLib
# ============================================================================

class TestAPKNativeLibDataclass:

    def test_creation(self):
        from redb.models.dataclasses import APKNativeLib

        lib = APKNativeLib(
            abi="arm64-v8a",
            filename="libnative.so",
            size=200000,
            sha256="ff" * 32,
        )
        assert lib.abi == "arm64-v8a"
        assert lib.filename == "libnative.so"
        assert lib.is_known_packer is False

    def test_known_packer(self):
        from redb.models.dataclasses import APKNativeLib

        lib = APKNativeLib(
            abi="armeabi-v7a",
            filename="libjiagu.so",
            size=100000,
            sha256="aa" * 32,
            is_known_packer=True,
        )
        assert lib.is_known_packer is True


# ============================================================================
# APKInconsistencyTests
# ============================================================================

class TestAPKInconsistencyTestsDataclass:

    def test_all_defaults_none(self):
        from redb.models.dataclasses import APKInconsistencyTests

        t = APKInconsistencyTests()
        assert t.test_zip_bomb is None
        assert t.test_zip_duplicate_entries is None
        assert t.test_zip_path_traversal is None
        assert t.test_zip_suspicious_timestamps is None
        assert t.test_hidden_dex_files is None
        assert t.test_manifest_component_mismatch is None
        assert t.test_debuggable_release is None
        assert t.test_emulator_detection_strings is None
        assert t.test_debugger_detection is None
        assert t.test_root_detection is None

    def test_all_fields_populated(self):
        from redb.models.dataclasses import APKInconsistencyTests

        t = APKInconsistencyTests(
            test_zip_bomb=True,
            test_zip_duplicate_entries=False,
            test_zip_path_traversal=True,
            test_zip_suspicious_timestamps=False,
            test_hidden_dex_files=True,
            test_manifest_component_mismatch=False,
            test_debuggable_release=True,
            test_emulator_detection_strings=True,
            test_debugger_detection=False,
            test_root_detection=True,
        )
        assert t.test_zip_bomb is True
        assert t.test_debuggable_release is True
        # Count true values
        d = asdict(t)
        true_count = sum(1 for v in d.values() if v is True)
        assert true_count == 6

    def test_field_count(self):
        from redb.models.dataclasses import APKInconsistencyTests

        # Exactly 10 inconsistency tests per PDD specification
        assert len(fields(APKInconsistencyTests)) == 10


# ============================================================================
# Hashes dataclass — APK permhash field
# ============================================================================

class TestHashesAPKField:

    def test_permhash_default_none(self):
        from redb.models.dataclasses import Hashes

        h = Hashes(md5="a", sha1="b", sha256="c", ssdeep_hash="d", tlsh_hash="e")
        assert h.permhash is None

    def test_permhash_populated(self):
        from redb.models.dataclasses import Hashes

        h = Hashes(
            md5="a", sha1="b", sha256="c", ssdeep_hash="d", tlsh_hash="e",
            permhash="abc123" * 10 + "abcd",
        )
        assert h.permhash is not None
        assert len(h.permhash) == 64


# ============================================================================
# Tag enum — APK entries
# ============================================================================

class TestAPKTagEnum:

    def test_all_apk_tags_exist(self):
        from redb.extractors.enum import Tag

        expected_tags = [
            "APK_FEATURES", "APK_MANIFEST", "APK_PERMISSIONS", "APK_SIGNATURE",
            "APK_DEX", "APK_RESOURCES", "APK_NATIVE_LIBS", "APK_INCONSISTENCY_TESTS",
        ]
        for name in expected_tags:
            assert hasattr(Tag, name), f"Tag.{name} missing"

    def test_apk_tag_values(self):
        from redb.extractors.enum import Tag

        assert Tag.APK_FEATURES.value == "apk_features"
        assert Tag.APK_MANIFEST.value == "apk_manifest"
        assert Tag.APK_PERMISSIONS.value == "apk_permissions"
        assert Tag.APK_SIGNATURE.value == "apk_signature"
        assert Tag.APK_DEX.value == "apk_dex"
        assert Tag.APK_RESOURCES.value == "apk_resources"
        assert Tag.APK_NATIVE_LIBS.value == "apk_native_libs"
        assert Tag.APK_INCONSISTENCY_TESTS.value == "apk_inconsistency_tests"