J. Marc Overhage

84 papers A* 1Misc 42Journal 36Unranked 5
YearRankTypeTitle / Venue / Authors
2024 J jnl
Appl. Clin. Inform.
J. Marc Overhage, Fares Qeadan, Eun Ho Eunice Choi, Duncan Vos, Philip J. Kroth
2023 A* conf
CHI
Eleanor R. Burgess, Ivana Jankovic, Melissa Austin, Nancy Cai, Adela Kapuscinska, Suzanne Currie, J. Marc Overhage, Erika S. Poole, Jofish Kaye
2022 Misc conf
AMIA
Natalya Maisel, J. Marc Overhage, Robert Thombley, Kathleen Blake, Christine A. Sinsky, Lindsey E. Carlasare, Julia Adler-Milstein
2019 Misc conf
AMIA
Julia Adler-Milstein, You Chen, Michelle R. Hribar, Jennifer R. Popovic, J. Marc Overhage
2019 J jnl
CoRR
Sunil Mallya, J. Marc Overhage, Navneet Srivastava, Tatsuya Arai, Cole Erdman
2019 J jnl
CoRR
Sunil Mallya, J. Marc Overhage, Sravan Bodapati, Navneet Srivastava, Sahika Genc
2018 Misc conf
AMIA
Jodi Kodish-Wachs, J. Marc Overhage, Patrick Kenny III, Emin Agassi
2018 Misc conf
AMIA
J. Marc Overhage, Titus K. Schleyer, Shaun J. Grannis, Allan Fong, Raj M. Ratwani
2018 Misc conf
AMIA
Aziz A. Boxwala, Blackford Middleton, J. Marc Overhage, Julia Adler-Milstein
2017 conf
MedInfo
Lauren M. Overhage, Jennifer Covich-Bordenick, Xiouchun Li, J. Marc Overhage
2017 Misc conf
AMIA
Blackford Middleton, Aziz A. Boxwala, J. Marc Overhage, James Doyle, Todd Rothenhaus
2017 conf
MedInfo
Vivienne J. Zhu, J. Marc Overhage, Qianli Ma, Patrick B. Ryan
2016 J jnl
CoRR
Volker Tresp, J. Marc Overhage, Markus Bundschus, Shahrooz Rabizadeh, Peter A. Fasching, Shipeng Yu
2016 J jnl
Proc. IEEE
Volker Tresp, J. Marc Overhage, Markus Bundschus, Shahrooz Rabizadeh, Peter A. Fasching, Shipeng Yu
2015 Misc conf
AMIA
Vivienne J. Zhu, Wanzhu Tu, Marc B. Rosenman, J. Marc Overhage
2015 conf
MedInfo
Vivienne J. Zhu, Wanzhu Tu, Marc B. Rosenman, J. Marc Overhage
2014 Misc conf
AMIA
Vivienne J. Zhu, Wanzhu Tu, Marc B. Rosenman, J. Marc Overhage
2014 Misc conf
AMIA
Shipeng Yu, J. Marc Overhage, Paul C. Tang
2013 Misc conf
AMIA
Vivienne J. Zhu, Patrick B. Ryan, J. Marc Overhage, Paul E. Stang, Jesse Berlin
2013 Misc conf
AMIA
Titus Schleyer, Blackford Middleton, Bret Shillingstad, J. Marc Overhage, Constantin F. Aliferis
2013 J jnl
J. Am. Medical Informatics Assoc.
Paul C. Tang, J. Marc Overhage, Albert Solomon Chan, Nancy L. Brown, Bahar Aghighi, Martin P. Entwistle, Siu Lui Hui, Shauna M. Hyde, Linda H. Klieman, Charlotte J. Mitchell, Anthony J. Perkins, Lubna Qureshi, Tanya A. Waltimyer, Leigha J. Winters, Charles Y. Young
2012 Misc conf
AMIA
Vivienne J. Zhu, Wanzhu Tu, David G. Marrero, Marc B. Rosenman, J. Marc Overhage
2012 J jnl
PLoS Comput. Biol.
Jon D. Duke, Xu Han, Zhiping Wang, Abhinita Subhadarshini, Shreyas D. Karnik, Xiaochun Li, Stephen D. Hall, Yan Jin, J. Thomas Callaghan, J. Marc Overhage, David A. Flockhart, R. Matthew Strother, Sara K. Quinney, Lang Li
2012 Misc conf
AMIA
Blaine Y. Takesue, J. Marc Overhage, Shaun J. Grannis, Jane Wang, Siu L. Hui, Marc B. Rosenman
2012 J jnl
J. Am. Medical Informatics Assoc.
J. Marc Overhage, Patrick B. Ryan, Christian G. Reich, Abraham G. Hartzema, Paul E. Stang
2010 J jnl
J. Am. Medical Informatics Assoc.
Brian E. Dixon, Atif Zafar, J. Marc Overhage
2010 J jnl
J. Am. Medical Informatics Assoc.
Kevin Chen-Chuan Chang, J. Marc Overhage, Siu L. Hui, Martin Chieng Were
2009 J jnl
J. Am. Medical Informatics Assoc.
Reed M. Gardner, J. Marc Overhage, Elaine B. Steen, Benson S. Munger, John H. Holmes, Jeffrey J. Williamson, Don E. Detmer
2009 Misc conf
AMIA
Linas Simonaitis, Brian E. Dixon, Anne W. Belsito, Theda Miller, J. Marc Overhage
2009 J jnl
J. Am. Medical Informatics Assoc.
Walter V. Sujansky, J. Marc Overhage, Sophia Chang, Jonah Frohlich, Samuel A. Faus
2009 J jnl
J. Am. Medical Informatics Assoc.
Vivienne J. Zhu, J. Marc Overhage, James Egg, Stephen M. Downs, Shaun J. Grannis
2008 Misc conf
AMIA
Linas Simonaitis, Anne W. Belsito, J. Marc Overhage
2008 Misc conf
AMIA
Jeff Friedlin, Shaun J. Grannis, J. Marc Overhage
2007 Misc conf
AMIA
Daniel J. Vreeman, John T. Finnell, J. Marc Overhage
2007 conf
MedInfo
Julie J. McGowan, Margaret W. Richwine, J. Marc Overhage
2007 Misc conf
AMIA
Carl A. Williams, Angelia D. Mosley-Williams, J. Marc Overhage
2007 Misc conf
AMIA
Jeff Friedlin, Paul Richard Dexter, J. Marc Overhage
2007 Misc conf
AMIA
Julie J. McGowan, Cy Jordan, Thomas Sims, J. Marc Overhage
2007 J jnl
J. Biomed. Informatics
George Hripcsak, Rainu Kaushal, Kevin B. Johnson, Joan S. Ash, David W. Bates, Rachel Block, Mark E. Frisse, Lisa M. Kern, Janet Marchibroda, J. Marc Overhage, Adam B. Wilcox
2006 Misc conf
AMIA
Philip J. Kroth, Paul Richard Dexter, J. Marc Overhage, Cynthia Knipe, Siu L. Hui, Anne W. Belsito, Clement J. McDonald
2006 J jnl
J. Am. Medical Informatics Assoc.
Christopher A. Cassa, Shaun J. Grannis, J. Marc Overhage, Kenneth D. Mandl
2006 Misc conf
AMIA
Shaun J. Grannis, Michael Wade, P. Joseph Gibson, J. Marc Overhage
2006 J jnl
J. Am. Medical Informatics Assoc.
Paul C. Tang, Joan S. Ash, David W. Bates, J. Marc Overhage, Daniel Z. Sands
2005 Misc conf
AMIA
Shaun J. Grannis, Paul G. Biondich, Burke W. Mamlin, M. D. Greg Wilson, Linda Jones, J. Marc Overhage
2005 Misc conf
AMIA
John T. Finnell, J. Marc Overhage, Clement J. McDonald
2005 Misc conf
AMIA
Shaun J. Grannis, James Egg, J. Marc Overhage
2005 Misc conf
AMIA
Clement J. McDonald, Paul Richard Dexter, Gunther Schadow, Henry C. Chueh, Greg Abernathy, John Hook, Lonnie Blevins, J. Marc Overhage, Jules J. Berman
2005 J jnl
J. Am. Medical Informatics Assoc.
J. Marc Overhage
2005 J jnl
J. Am. Medical Informatics Assoc.
J. Marc Overhage, Lori Evans, Janet Marchibroda
2004 J jnl
Int. J. Medical Informatics
Atif Zafar, Burke W. Mamlin, Susan M. Perkins, Anne W. Belsito, J. Marc Overhage, Clement J. McDonald
2004 J jnl
J. Am. Medical Informatics Assoc.
Clement J. McDonald, J. Marc Overhage, Burke W. Mamlin, Paul Richard Dexter, William M. Tierney
2004 J jnl
J. Am. Medical Informatics Assoc.
William A. Yasnoff, Betsy L. Humphreys, J. Marc Overhage, Don E. Detmer, Patricia Flatley Brennan, Richard W. Morris, Blackford Middleton, David W. Bates, John P. Fanning
2004 conf
MedInfo
Shaun J. Grannis, J. Marc Overhage, Clement J. McDonald
2004 J jnl
J. Am. Medical Informatics Assoc.
Kenneth D. Mandl, J. Marc Overhage, Michael M. Wagner, William B. Lober, Paola Sebastiani, Farzad Mostashari, Julie A. Pavlin, Per H. Gesteland, Tracee Treadwell, Eileen Koski, Lori Hutwagner, David L. Buckeridge, Raymond D. Aller, Shaun J. Grannis
2003 J jnl
J. Biomed. Informatics
Carol Hope, J. Marc Overhage, Andrew C. Seger, Evgenia Y. Teal, Vera Mills, Julie M. Fiskio, Tejal K. Gandhi, David W. Bates, Michael D. Murray
2003 Misc conf
AMIA
Shaun J. Grannis, J. Marc Overhage, Siu L. Hui, Clement J. McDonald
2003 Misc conf
AMIA
John T. Finnell, J. Marc Overhage, Paul Richard Dexter, Susan M. Perkins, Kathleen A. Lane, Clement J. McDonald
2003 Misc conf
AMIA
Marc B. Rosenman, Jane Wang, Paul Richard Dexter, J. Marc Overhage
2003 J jnl
Int. J. Medical Informatics
Clement J. McDonald, Gunther Schadow, Michael Barnes, Paul Richard Dexter, J. Marc Overhage, Burke W. Mamlin, J. Michael McCoy
2003 Misc conf
AMIA
Burke W. Mamlin, Gunther Schadow, J. Marc Overhage
2003 J jnl
J. Am. Medical Informatics Assoc.
William R. Hogan, Fu-Chiang Tsui, Oleg Ivanov, Per H. Gesteland, Shaun J. Grannis, J. Marc Overhage, J. Michael Robinson, Michael M. Wagner
2002 Misc conf
AMIA
Paul G. Biondich, J. Marc Overhage, Paul Richard Dexter, Stephen M. Downs, Larry Lemmon, Clement J. McDonald
2002 Misc conf
AMIA
Shaun J. Grannis, J. Marc Overhage, Clement J. McDonald
2002 J jnl
J. Am. Medical Informatics Assoc.
J. Marc Overhage, Blackford Middleton, Randolph A. Miller, Rita D. Zielstorff, William R. Hersh
2002 J jnl
J. Am. Medical Informatics Assoc.
William B. Lober, Bryant Thomas Karras, Michael M. Wagner, J. Marc Overhage, Arthur J. Davidson, Hamish Fraser, Lisa J. Trigg, Kenneth D. Mandl, Jeremy U. Espino, Fu-Chiang Tsui
2002 Misc conf
AMIA
Clement J. McDonald, J. Marc Overhage, Paul Richard Dexter, Michael Barnes, Jeffrey G. Suico, Michael Weiner, Gunther Schadow, Greg Abernathy, William M. Tierney, Lonnie Blevins, Larry Lemmon, Tull T. Glazener, Pat Cassidy, Diane Xu, Megan Geng, Brian Porterfield, Mark Tucker, Mike Edwards, John Hook, John Clifford, Donald Lindbergh, Anne W. Belsito, Bruce Williams, Jeff S. Warvel, Jill Warvel
2001 Misc conf
AMIA
Sean M. Thomas, J. Marc Overhage, Jeff S. Warvel, Clement J. McDonald
2001 Misc conf
AMIA
Philip J. Kroth, Anne W. Belsito, J. Marc Overhage, Clement J. McDonald
2001 Misc conf
AMIA
J. Marc Overhage, Alex M. Aisen, Michael Barnes, Mark Tucker, Clement J. McDonald
2001 J jnl
J. Am. Medical Informatics Assoc.
J. Marc Overhage, Susan M. Perkins, William M. Tierney, Clement J. McDonald
2001 Misc conf
AMIA
Clement J. McDonald, Michael Barnes, J. Marc Overhage, Jeffrey G. Suico, Paul Richard Dexter, Gunther Schadow, Burke W. Mamlin, Atif Zafar, William M. Tierney, Lonnie Blevins, Larry Lemmon, Tull T. Glazener, Pat Cassidy, Diane Xu, Mark Tucker, Mike Edwards, Donald Lindbergh, Anne W. Belsito, Bruce Williams, Jeff S. Warvel, Jill Warvel
2001 J jnl
J. Am. Medical Informatics Assoc.
William A. Yasnoff, J. Marc Overhage, Betsy L. Humphreys, Martin LaVenture
2001 J jnl
J. Am. Medical Informatics Assoc.
David W. Bates, Michael Cohen, Lucian Leape, J. Marc Overhage, M. Michael Shabot, Thomas B. Sheridan
2000 Misc conf
AMIA
Robert L. Herting Jr., Joseph W. Hales, J. Marc Overhage
2000 Misc conf
AMIA
J. Marc Overhage, Clement J. McDonald, Jeffrey G. Suico
1999 J jnl
J. Am. Medical Informatics Assoc.
Philip P. Breitfeld, Marina Weisburd, J. Marc Overhage, George Sledge Jr., William M. Tierney
1999 J jnl
J. Am. Medical Informatics Assoc.
Atif Zafar, J. Marc Overhage, Clement J. McDonald
1999 Misc conf
AMIA
Clement J. McDonald, J. Marc Overhage, Paul Richard Dexter, William M. Tierney, Jeffrey G. Suico, Alex M. Aisen, Atif Zafar, Gunther Schadow, Lonnie Blevins, Jill Warvel, Jeff S. Warvel, Jim Meeks-Johnson, Larry Lemmon, Tull T. Glazener, Anne W. Belsito, Donald Lindbergh, Bruce Williams, Pat Cassidy, Diane Xu, Mark Tucker, Mike Edwards, Cheryl Wodniak, Brenda Smith, Terry Hogan
1999 J jnl
Int. J. Medical Informatics
Clement J. McDonald, J. Marc Overhage, William M. Tierney, Paul Richard Dexter, Douglas K. Martin, Jeffrey G. Suico, Atif Zafar, Gunther Schadow, Lonnie Blevins, Tull T. Glazener, Jim Meeks-Johnson, Larry Lemmon, Jill Warvel, Brian Porterfield, Jeff S. Warvel, Pat Cassidy, Donald Lindbergh, Anne W. Belsito, Mark Tucker, Bruce Williams, Cheryl Wodniak
1998 Misc conf
AMIA
Clement J. McDonald, J. Marc Overhage, William M. Tierney, Paul Richard Dexter, Jeffrey G. Suico, Atif Zafar, Brenda Smith, Terry Hogan, Lonnie Blevins, Jill Warvel, Jeff S. Warvel, Jim Meeks-Johnson, Larry Lemmon, Tull T. Glazener, Anne W. Belsito, Donald Lindbergh, Bruce Williams, Pat Cassidy, Diane Xu, Mark Tucker, Mike Edwards
1997 J jnl
J. Am. Medical Informatics Assoc.
J. Marc Overhage, William M. Tierney, Xiao-Hua Zhou, Clement J. McDonald
1997 Misc conf
AMIA
Clement J. McDonald, J. Marc Overhage, William M. Tierney, Paul Richard Dexter, Blaine Y. Takesue, Brenda Smith, Terry Hogan, Lonnie Blevins, Jill Warvel, Jeff S. Warvel, Jim Meeks-Johnson, Larry Lemmon, Tull T. Glazener, Anne W. Belsito, Donald Lindbergh, Bruce Williams, Pat Cassidy, Diane Xu, Mark Tucker
1995 J jnl
J. Am. Medical Informatics Assoc.
William M. Tierney, J. Marc Overhage, Blaine Y. Takesue, Lisa E. Harris, Michael D. Murray, Dennis L. Vargo, Clement J. McDonald
1994 J jnl
J. Am. Medical Informatics Assoc.
William M. Tierney, J. Marc Overhage, Clement J. McDonald
tests/unit/test_smali_normalization.py
← Index tests/unit/test_smali_normalization.py python
"""Unit tests for smali semantic normalization.

Tests the three normalization levels (category, opcode, opcode_api),
opcode categorization, ACFG feature index mapping, and integration
with MinHash computation.
"""
import pytest

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


class TestCategorizeOpcode:
    """Tests for opcode -> semantic category mapping."""

    def test_arithmetic(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("add-int") == "ALU"
        assert categorize_opcode("mul-long/2addr") == "ALU"
        assert categorize_opcode("neg-int") == "ALU"

    def test_data_movement(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("move-result") == "MOV"
        assert categorize_opcode("const/4") == "CONST"
        assert categorize_opcode("const-string") == "CONST"

    def test_memory_access(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("iget-object") == "LOAD"
        assert categorize_opcode("sput-wide") == "STORE"
        assert categorize_opcode("aget-byte") == "LOAD"

    def test_invocation(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("invoke-virtual") == "CALL"
        assert categorize_opcode("invoke-static") == "CALL"
        assert categorize_opcode("invoke-direct") == "CALL"

    def test_control_flow(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("if-eqz") == "BRANCH"
        assert categorize_opcode("goto") == "JMP"
        assert categorize_opcode("goto/16") == "JMP"
        assert categorize_opcode("return-void") == "RET"

    def test_comparison(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("cmp-long") == "CMP"
        assert categorize_opcode("cmpl-float") == "CMP"
        assert categorize_opcode("cmpg-double") == "CMP"

    def test_conversion(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("int-to-long") == "CONV"
        assert categorize_opcode("float-to-int") == "CONV"

    def test_object_type(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("new-instance") == "ALLOC"
        assert categorize_opcode("check-cast") == "TYPE"
        assert categorize_opcode("instance-of") == "TYPE"

    def test_exception_sync(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("throw") == "EXC"
        assert categorize_opcode("monitor-enter") == "SYNC"

    def test_unknown(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("nop") == "OTHER"


class TestNormalizeInstruction:
    """Tests for single instruction normalization at various levels."""

    def test_category_level(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        assert normalize_instruction("add-int v0, v1, v2", "category") == "ALU"
        assert normalize_instruction("invoke-virtual {p0}, Lcom/Foo;->bar()V", "category") == "CALL"
        assert normalize_instruction("return-void", "category") == "RET"

    def test_opcode_level_strips_width(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        # Width variants collapse to same base
        assert normalize_instruction("add-int v0, v1, v2", "opcode") == "add"
        assert normalize_instruction("add-long v0, v2, v4", "opcode") == "add"
        assert normalize_instruction("add-float v0, v1, v2", "opcode") == "add"
        # Addressing modes collapse too
        assert normalize_instruction("add-int/2addr v0, v1", "opcode") == "add"

    def test_opcode_api_invoke(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        result = normalize_instruction(
            "invoke-virtual {p0, v0}, Lcom/example/Foo;->bar(I)V"
        )
        assert result == "CALL Lcom/example/Foo;->bar(I)V"

    def test_opcode_api_invoke_no_ref(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        # If somehow no method ref is found, fallback to CALL
        assert normalize_instruction("invoke-virtual {v0}") == "CALL"

    def test_opcode_api_field_load(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        result = normalize_instruction(
            "iget-object v0, p0, Lcom/Foo;->mField:Ljava/lang/String;"
        )
        assert result == "LOAD Lcom/Foo;->mField:Ljava/lang/String;"

    def test_opcode_api_field_store(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        result = normalize_instruction(
            "iput-object v0, p0, Lcom/Foo;->mField:Ljava/lang/String;"
        )
        assert result == "STORE Lcom/Foo;->mField:Ljava/lang/String;"

    def test_opcode_api_androguard_field_format(self):
        """androguard uses space instead of colon in field references."""
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        result = normalize_instruction(
            "iget-object v0, p0, Lcom/Foo;->mField Ljava/lang/String;"
        )
        assert result.startswith("LOAD")
        assert "Lcom/Foo;->mField" in result

    def test_opcode_api_new_instance(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        result = normalize_instruction(
            "new-instance v0, Lcom/example/MyClass;"
        )
        assert result == "ALLOC Lcom/example/MyClass;"

    def test_opcode_api_const_string(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        result = normalize_instruction(
            'const-string v0, "hello world"'
        )
        assert result == 'CONST_STR "hello world"'

    def test_opcode_api_const_string_jumbo(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        result = normalize_instruction(
            'const-string/jumbo v0, "large string"'
        )
        assert result == 'CONST_STR "large string"'

    def test_opcode_api_fallback_to_category(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        # Non-special instructions fall back to category
        assert normalize_instruction("add-int v0, v1, v2") == "ALU"
        assert normalize_instruction("return-void") == "RET"
        assert normalize_instruction("nop") == "OTHER"

    def test_empty_input(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        assert normalize_instruction("") == ""
        assert normalize_instruction("   ") == ""


class TestNormalizeMethodBody:
    """Tests for full method body normalization."""

    def test_filters_directives_labels_comments(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_method_body
        body = """\
.locals 2
# comment
:label_0
add-int v0, v1, v2
.line 42
invoke-virtual {p0}, Lcom/Foo;->bar()V
return-void
"""
        result = normalize_method_body(body, "category")
        assert result == ["ALU", "CALL", "RET"]

    def test_opcode_api_preserves_api_refs(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_method_body
        body = """\
const/4 v0, 0x0
invoke-virtual {p0, v0}, Lcom/Foo;->setX(I)V
iget-object v1, p0, Lcom/Foo;->name:Ljava/lang/String;
return-void
"""
        result = normalize_method_body(body, "opcode_api")
        assert result[0] == "CONST"
        assert result[1] == "CALL Lcom/Foo;->setX(I)V"
        assert result[2] == "LOAD Lcom/Foo;->name:Ljava/lang/String;"
        assert result[3] == "RET"

    def test_empty_body(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_method_body
        assert normalize_method_body("") == []
        assert normalize_method_body("\n\n") == []


class TestNormalizationWithMinHash:
    """Integration tests: normalization + MinHash computation."""

    def test_minhash_returns_signature(self):
        from redb.extractors.decompiler.apk.method_extractor import compute_minhash
        body = """\
const/4 v0, 0x0
invoke-virtual {p0, v0}, Lcom/Foo;->bar(I)V
iget-object v1, p0, Lcom/Foo;->name:Ljava/lang/String;
add-int v2, v0, v1
return-void
"""
        sig = compute_minhash(body)
        assert sig is not None
        assert len(sig) == 64
        assert all(0 <= v < 256 for v in sig)

    def test_minhash_register_invariance(self):
        """Same operations with different registers should produce identical signatures."""
        from redb.extractors.decompiler.apk.method_extractor import compute_minhash
        body_a = """\
const/4 v0, 0x0
invoke-virtual {p0, v0}, Lcom/Foo;->bar(I)V
iget-object v1, p0, Lcom/Foo;->name:Ljava/lang/String;
add-int v2, v0, v1
return-void
"""
        body_b = """\
const/4 v3, 0x0
invoke-virtual {p1, v3}, Lcom/Foo;->bar(I)V
iget-object v4, p1, Lcom/Foo;->name:Ljava/lang/String;
add-int v5, v3, v4
return-void
"""
        sig_a = compute_minhash(body_a)
        sig_b = compute_minhash(body_b)
        assert sig_a == sig_b

    def test_minhash_width_invariance(self):
        """Width variants of same operations should produce identical signatures."""
        from redb.extractors.decompiler.apk.method_extractor import compute_minhash
        body_int = """\
add-int v0, v1, v2
sub-int v3, v0, v1
mul-int v4, v0, v3
return v4
"""
        body_long = """\
add-long v0, v2, v4
sub-long v6, v0, v2
mul-long v8, v0, v6
return-wide v8
"""
        sig_int = compute_minhash(body_int)
        sig_long = compute_minhash(body_long)
        # Both normalize to ALU, ALU, ALU, RET -> identical
        assert sig_int == sig_long

    def test_minhash_different_apis_differ(self):
        """Methods calling different APIs should produce different signatures."""
        from redb.extractors.decompiler.apk.method_extractor import compute_minhash
        body_a = """\
const/4 v0, 0x0
invoke-virtual {p0, v0}, Lcom/crypto/AES;->encrypt([B)[B
invoke-virtual {v0}, Ljava/io/OutputStream;->write([B)V
return-void
"""
        body_b = """\
const/4 v0, 0x0
invoke-virtual {p0, v0}, Ljava/lang/String;->length()I
invoke-virtual {v0}, Ljava/io/PrintStream;->println(I)V
return-void
"""
        sig_a = compute_minhash(body_a)
        sig_b = compute_minhash(body_b)
        assert sig_a != sig_b

    def test_minhash_too_few_instructions(self):
        from redb.extractors.decompiler.apk.method_extractor import compute_minhash
        assert compute_minhash("return-void\nnop") is None


class TestACFGBlockFeatures:
    """Tests for per-block ACFG feature extraction via smali_cfg."""

    def test_simple_linear_method(self):
        from redb.extractors.decompiler.apk.smali_cfg import compute_cfg_metrics
        body = """\
add-int v0, v1, v2
invoke-virtual {p0}, Lcom/Foo;->bar()V
return-void
"""
        metrics = compute_cfg_metrics(body)
        assert metrics.block_count >= 1
        assert len(metrics.block_features) == metrics.block_count
        # Each feature vector has 8 elements
        for feat in metrics.block_features:
            assert len(feat) == 8

    def test_branching_method_has_multiple_blocks(self):
        from redb.extractors.decompiler.apk.smali_cfg import compute_cfg_metrics
        body = """\
const/4 v0, 0x0
if-eqz v0, :cond_0
invoke-virtual {p0}, Lcom/Foo;->a()V
goto :goto_0
:cond_0
invoke-virtual {p0}, Lcom/Foo;->b()V
:goto_0
return-void
"""
        metrics = compute_cfg_metrics(body)
        assert metrics.block_count >= 3
        assert len(metrics.block_features) == metrics.block_count

    def test_feature_vector_arithmetic_count(self):
        from redb.extractors.decompiler.apk.smali_cfg import compute_cfg_metrics
        body = """\
add-int v0, v1, v2
sub-int v3, v0, v1
mul-int v4, v0, v3
return v4
"""
        metrics = compute_cfg_metrics(body)
        assert len(metrics.block_features) == 1
        feat = metrics.block_features[0]
        # feat[0] = instr_count (4), feat[1] = arithmetic (3)
        assert feat[0] == 4
        assert feat[1] >= 3  # 3 ALU ops

    def test_feature_vector_call_count(self):
        from redb.extractors.decompiler.apk.smali_cfg import compute_cfg_metrics
        body = """\
invoke-virtual {p0}, Lcom/A;->a()V
invoke-static {v0}, Lcom/B;->b()V
return-void
"""
        metrics = compute_cfg_metrics(body)
        feat = metrics.block_features[0]
        # feat[4] = call count
        assert feat[4] == 2