Xiaochao Dang

58 papers B 1Journal 42Unranked 14
YearRankTypeTitle / Venue / Authors
2026 J jnl
Appl. Intell.
Xiaochao Dang, Xiaoling Shu, Xiaohui Dong, Fenfang Li
2025 J jnl
Artif. Intell. Rev.
Xiaohui Dong, Zhengluo Li, Haoming Su, Jixiang Xue, Xiaochao Dang
2025 J jnl
ACM Trans. Asian Low Resour. Lang. Inf. Process.
Xiaochao Dang, Guozhen Ding, Xiaohui Dong, Fenfang Li, Shiwei Gao, Yue Wang
2024 J jnl
IEEE Internet Things J.
Zhanjun Hao, Yuejiao Wang, Zhenyi Zhang, Xiaochao Dang
2024 J jnl
Sensors
Xiaochao Dang, Yangyang Tang, Zhanjun Hao, Yifei Gao, Kai Fan, Yue Wang
2024 J jnl
Inf.
Xiaochao Dang, Xiaoling Shu, Fenfang Li, Xiaohui Dong
2024 J jnl
Neural Process. Lett.
Shiwei Gao, Yufeng Zeng, Xiaochao Dang, Xiaohui Dong
2024 J jnl
IEEE Trans. Instrum. Meas.
Shiwei Gao, Tianzhen Li, Xiaohui Dong, Xiaochao Dang
2024 J jnl
Symmetry
Xiaoling Shu, Xiaochao Dang, Xiaohui Dong, Fenfang Li
2024 J jnl
Sensors
Zhanjun Hao, Kaikai Han, ZiNan Zhang, Xiaochao Dang
2023 J jnl
Sensors
Xiaochao Dang, Peng Jin, Zhanjun Hao, Wenze Ke, Han Deng, Li Wang
2023 J jnl
Sensors
Yuejiao Wang, Zhanjun Hao, Xiaochao Dang, Zhenyi Zhang, Mengqiao Li
2023 J jnl
Sensors
Xiaochao Dang, Zetong Chen, Zhanjun Hao, Macidan Ga, Xinyu Han, Xiaotong Zhang, Jie Yang
2023 J jnl
Sensors
Xiaochao Dang, Wenze Ke, Zhanjun Hao, Peng Jin, Han Deng, Ying Sheng
2022 J jnl
Sensors
Xiaochao Dang, Jinlong Zhang, Zhanjun Hao
2022 J jnl
Sensors
Zhanjun Hao, Hao Yan, Xiaochao Dang, Zhongyu Ma, Peng Jin, Wenze Ke
2022 conf
MORSE@MobiCom
Zhanjun Hao, Hao Yan, Xiaochao Dang, Zhongyu Ma, Wenze Ke, Peng Jin
2022 conf
WASA (2)
Zhanjun Hao, Yuejiao Wang, Daiyang Zhang, Xiaochao Dang
2022 conf
WASA (1)
Xiaochao Dang, Yanhong Bai, Daiyang Zhang, Gaoyuan Liu, Zhanjun Hao
2022 J jnl
Sensors
Zhanjun Hao, Juan Niu, Xiaochao Dang, Zhiqiang Qiao
2022 J jnl
Sensors
Zhanjun Hao, Zepei Li, Xiaochao Dang, Zhongyu Ma, Yue Wang
2022 J jnl
Sensors
Zhanjun Hao, Jianxiang Peng, Xiaochao Dang, Hao Yan, Ruidong Wang
2021 conf
HPCC/DSS/SmartCity/DependSys
Zhanjun Hao, Gaoyuan Liu, Xiaochao Dang, Daiyang Zhang, Yanhong Bai, HongWen Xu
2021 J jnl
Int. J. Distributed Sens. Networks
Zhanjun Hao, Jiaojiao Hou, Jianwu Dang, Xiaochao Dang, Nanjiang Qu
2021 B conf
ICPADS
Zhanjun Hao, Daiyang Zhang, Yu Duan, Xiaochao Dang
2021 J jnl
Telecommun. Syst.
Zhongyu Ma, Yanxing Liu, Qun Guo, Xiaochao Dang, Zhanjun Hao, Ran Tian
2021 J jnl
Sensors
Zhanjun Hao, Daiyang Zhang, Xiaochao Dang, Gaoyuan Liu, Yanhong Bai
2020 conf
CWSN
Xiaochao Dang, Yuexia Li, Zhanjun Hao
2020 J jnl
Wirel. Commun. Mob. Comput.
Xiaochao Dang, Yang Liu, Zhanjun Hao, Xuhao Tang, Chenguang Shao
2020 J jnl
Mob. Inf. Syst.
Zhanjun Hao, Yu Duan, Xiaochao Dang, Tong Zhang
2020 J jnl
EURASIP J. Wirel. Commun. Netw.
Xiaochao Dang, Xuhao Tang, Zhanjun Hao, Jiaju Ren
2020 J jnl
J. Sensors
Zhanjun Hao, HongWen Xu, Xiaochao Dang, Nanjiang Qu
2020 J jnl
Neural Networks
Xiangwen Wang, Xianghong Lin, Xiaochao Dang
2020 J jnl
Sensors
Zhanjun Hao, Yu Duan, Xiaochao Dang, Yang Liu, Daiyang Zhang
2020 J jnl
Sensors
Xiaochao Dang, Yuan Cao, Zhanjun Hao, Yang Liu
2020 ed.
CWSN
Zhanjun Hao, Xiaochao Dang, Honghong Chen, Fenfang Li
2019 conf
CWSN
Xiaochao Dang, Yuexia Li, Zhanjun Hao, Tong Zhang
2019 conf
CWSN
Xiaochao Dang, Caixia Li, Zhanjun Hao, Yuan Cao
2019 J jnl
Sensors
Xiaochao Dang, Xuhao Tang, Zhanjun Hao, Yang Liu
2019 conf
CWSN
Zhanjun Hao, Lihua Yan, Xiaochao Dang
2019 J jnl
Sensors
Xiaochao Dang, Xiong Si, Zhanjun Hao, Yaning Huang
2019 J jnl
Int. J. Distributed Sens. Networks
Xiaochao Dang, Jiaju Ren, Zhanjun Hao, Yili Hei, Xuhao Tang, Yan Yan
2019 J jnl
J. Sensors
Xiaochao Dang, Chenguang Shao, Zhanjun Hao
2019 J jnl
Sensors
Zhanjun Hao, Yan Yan, Xiaochao Dang, Chenguang Shao
2019 J jnl
Int. J. Distributed Sens. Networks
Zhanjun Hao, Nanjiang Qu, Xiaochao Dang, Jiaojiao Hou
2019 J jnl
IEEE Access
Zhanjun Hao, Nanjiang Qu, Xiaochao Dang, Jiaojiao Hou
2019 J jnl
Mob. Inf. Syst.
Xiaochao Dang, Chenguang Shao, Zhanjun Hao
2019 conf
CWSN
Xiaochao Dang, Tong Zhang, Zhanjun Hao, Yuexia Li
2018 conf
ICPCSEE (2)
Zhanjun Hao, Beibei Li, Xiaochao Dang
2018 J jnl
EURASIP J. Wirel. Commun. Netw.
Xiaochao Dang, Yaning Huang, Zhanjun Hao, Xiong Si
2018 conf
CWSN
Xiaochao Dang, Jiaju Ren, Zhanjun Hao, Yan Yan, Yili Hei
2017 conf
CWSN
Xiaochao Dang, Yili Hei, Zhanjun Hao
2017 conf
ICPCSEE (2)
Xiaochao Dang, Rucang Ma, Zhanjun Hao, Meixiu Ma
2016 conf
CITS
Xiaochao Dang, Yili Hei, Zhanjun Hao
2016 J jnl
EURASIP J. Wirel. Commun. Netw.
Xiangdong Jia, Meng Zhou, Xiaochao Dang, Longxiang Yang, Hongbo Zhu
2015 J jnl
EURASIP J. Wirel. Commun. Netw.
Xiangdong Jia, Dan Wang, Xiaochao Dang, Longxiang Yang, Hongbo Zhu
2014 J jnl
EURASIP J. Wirel. Commun. Netw.
Xiangdong Jia, Ming Zhou, Xiaochao Dang, Longxiang Yang, Hongbo Zhu
2014 J jnl
Int. J. Wavelets Multiresolution Inf. Process.
Xiaochao Dang, Zhan Jun Hao, Yan Li, Zhen Yu Lu, Qi Gao
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"