James Fogarty

127 papers A* 59A 17B 8C 1Misc 4Journal 23Unranked 14
YearRankTypeTitle / Venue / Authors
2026 A* conf
CHI
Seokhyun Hwang, Xiyuan Shen, Alexandre L. S. Filipowicz, Andrew Best, Jean Costa, Scott A. Carter, James Fogarty, Jacob O. Wobbrock
2026 A* conf
CHI
Mingyuan Zhong, Xia Chen, Davin Win Kyi, Chen Li, James Fogarty, Jacob O. Wobbrock
2025 A* conf
CHI
Aayushi Dangol, Aaleyah Lewis, Hyewon Suh, Xuesi Hong, Hedda Meadan, James Fogarty, Julie A. Kientz
2025 A* conf
CHI
Richard Li, Philip Vutien, Sabrina Omer, Michael Yacoub, George N. Ioannou, Ravi Karkar, Sean A. Munson, James Fogarty
2025 J jnl
Proc. ACM Interact. Mob. Wearable Ubiquitous Technol.
Shaan Chopra, Katherine Juarez, James Fogarty, Sean A. Munson
2025 conf
CHI Extended Abstracts
Tae E. Jones, James Fogarty, Sean A. Munson
2025 A* conf
CHI
Aaleyah Lewis, Aayushi Dangol, Hyewon Suh, Abbie Olszewski, James Fogarty, Julie A. Kientz
2025 A* conf
CHI
Aaleyah Lewis, Jesse J. Martinez, Maitraye Das, James Fogarty
2025 A conf
ASSETS
Kelly Avery Mack, Jesse J. Martinez, Aaleyah Lewis, Jennifer Mankoff, James Fogarty, Leah Findlater, Heather D. Evans, Cynthia L. Bennett, Emma J. McDonnell
2025 A* conf
CHI
Mingyuan Zhong, Ruolin Chen, Xia Chen, James Fogarty, Jacob O. Wobbrock
2025 J jnl
CoRR
Mingyuan Zhong, Ruolin Chen, Xia Chen, James Fogarty, Jacob O. Wobbrock
2025 J jnl
CoRR
Mingyuan Zhong, Xia Chen, Davin Win Kyi, Chen Li, James Fogarty, Jacob O. Wobbrock
2025 A* conf
UIST
Xiyuan Shen, Seokhyun Hwang, Junhan Kong, Alexandre L. S. Filipowicz, Andrew Best, Jean Costa, Scott A. Carter, James Fogarty, Jacob O. Wobbrock
2024 conf
CSCW Companion
Shaan Chopra, Abril Beretta, Miriana Duran, Katherine I. López, Janet A. Rojina, Linda K. Ko, Margaret Rosenfeld, Benjamin S. Wilfond, James Fogarty, Stephanie A. Kraft
2024 J jnl
Proc. ACM Hum. Comput. Interact.
Shaan Chopra, Lisa Orii, Katherine Juarez, Nussara Tieanklin, James Fogarty, Sean A. Munson
2024 A* conf
CHI
Yasaman S. Sefidgar, Carla L. Castillo, Shaan Chopra, Liwei Jiang, Tae Jones, Anant Mittal, Hyeyoung Ryu, Jessica Schroeder, Allison M. Cole, Natalia Murinova, Sean A. Munson, James Fogarty
2024 A* conf
CHI
Jesse J. Martinez, Jon E. Froehlich, James Fogarty
2024 J jnl
Proc. ACM Hum. Comput. Interact.
Junhan Kong, Mingyuan Zhong, James Fogarty, Jacob O. Wobbrock
2023 A conf
ASSETS
Anant Mittal, Meghna Gupta, Roshni Poddar, Tarini Naik, Seethalakshmi Kuppuraj, James Fogarty, Pratyush Kumar, Mohit Jain
2022 A* conf
CHI
Raymond Fok, Mingyuan Zhong, Anne Spencer Ross, James Fogarty, Jacob O. Wobbrock
2022 A conf
ASSETS
Junhan Kong, Mingyuan Zhong, James Fogarty, Jacob O. Wobbrock
2021 A* conf
CHI
Susanne Kirchner, Jessica Schroeder, James Fogarty, Sean A. Munson
2021 A conf
ASSETS
Jesse J. Martinez, James Fogarty, Jon E. Froehlich
2021 A conf
ASSETS
Junhan Kong, Mingyuan Zhong, James Fogarty, Jacob O. Wobbrock
2020 J jnl
ACM Trans. Access. Comput.
Anne Spencer Ross, Xiaoyi Zhang, James Fogarty, Jacob O. Wobbrock
2020 conf
PervasiveHealth
Jessica Schroeder, Jina Suh, Chelsey Wilkes, Mary Czerwinski, Sean A. Munson, James Fogarty, Tim Althoff
2020 J jnl
Proc. ACM Hum. Comput. Interact.
Laura R. Pina, Sang-Wha Sien, Clarissa Song, Teresa M. Ward, James Fogarty, Sean A. Munson, Julie A. Kientz
2020 J jnl
Proc. ACM Hum. Comput. Interact.
Jina Suh, Spencer Williams, Jesse R. Fann, James Fogarty, Amy M. Bauer, Gary Hsieh
2020 A* conf
CHI
Amanda Swearngin, Chenglong Wang, Alannah Oleson, James Fogarty, Amy J. Ko
2020 J jnl
CoRR
Amanda Swearngin, Chenglong Wang, Alannah Oleson, James Fogarty, Amy J. Ko
2020 J jnl
Frontiers Digit. Health
Sean A. Munson, Jessica Schroeder, Ravi Karkar, Julie A. Kientz, Chia-Fang Chung, James Fogarty
2020 B conf
Graphics Interface
Daniel A. Epstein, Mira Dontcheva, James Fogarty, Sean A. Munson
2019 J jnl
J. Heal. Informatics Res.
Jessica Schroeder, Ravi Karkar, James Fogarty, Julie A. Kientz, Sean A. Munson, Matthew Kay
2019 A conf
ASSETS
Leah Perlmutter, Bindita Chaudhuri, Justin Petelka, Philip Garrison, James Fogarty, Jacob O. Wobbrock, Richard E. Ladner
2019 J jnl
Proc. ACM Interact. Mob. Wearable Ubiquitous Technol.
Jessica Schroeder, Ravi Karkar, Natalia Murinova, James Fogarty, Sean A. Munson
2019 A conf
ASSETS
Bindita Chaudhuri, Leah Perlmutter, Justin Petelka, Philip Garrison, James Fogarty, Jacob O. Wobbrock, Richard E. Ladner
2019 J jnl
Proc. ACM Interact. Mob. Wearable Ubiquitous Technol.
Chia-Fang Chung, Qiaosi Wang, Jessica Schroeder, Allison M. Cole, Jasmine Zia, James Fogarty, Sean A. Munson
2019 ch.
Web Accessibility (2nd Ed.)
Mark S. Baldwin, Rushil Khurana, Duncan McIsaac, Yuqian Sun, Tracy Tran, Xiaoyi Zhang, James Fogarty, Gillian R. Hayes, Jennifer Mankoff
2018 J jnl
Proc. ACM Interact. Mob. Wearable Ubiquitous Technol.
Ravi Karkar, Rafal Kocielnik, Xiaoyi Zhang, Jasmine Zia, George N. Ioannou, Sean A. Munson, James Fogarty
2018 A conf
ASSETS
Anne Spencer Ross, Xiaoyi Zhang, James Fogarty, Jacob O. Wobbrock
2018 A conf
Conference on Designing Interactive Systems
Jessica Schroeder, Chia-Fang Chung, Daniel A. Epstein, Ravi Karkar, Adele Parsons, Natalia Murinova, James Fogarty, Sean A. Munson
2018 A conf
ASSETS
Xiaoyi Zhang, Tracy Tran, Yuqian Sun, Ian Culhane, Shobhit Jain, James Fogarty, Jennifer Mankoff
2018 A* conf
UIST
Xiaoyi Zhang, Anne Spencer Ross, James Fogarty
2018 conf
UIST (Adjunct Volume)
Amanda Swearngin, Amy J. Ko, James Fogarty
2017 J jnl
Comput. Support. Cooperative Work.
Kateryna Kuksenok, Cecilia M. Aragon, James Fogarty, Charlotte P. Lee, Gina Neff
2017 A conf
ASSETS
Anne Spencer Ross, Xiaoyi Zhang, James Fogarty, Jacob O. Wobbrock
2017 A* conf
CHI
Daniel A. Epstein, Nicole B. Lee, Jennifer H. Kang, Elena Agapie, Jessica Schroeder, Laura R. Pina, James Fogarty, Julie A. Kientz, Sean Munson
2017 A conf
CSCW
Laura R. Pina, Sang-Wha Sien, Teresa Ward, Jason C. Yip, Sean A. Munson, James Fogarty, Julie A. Kientz
2017 A* conf
CHI
Amanda Swearngin, Amy J. Ko, James Fogarty
2017 A* conf
CHI
Abigail C. Evans, Katie Davis, James Fogarty, Jacob O. Wobbrock
2017 A* conf
CHI
Xiaoyi Zhang, Anne Spencer Ross, Anat Caspi, James Fogarty, Jacob O. Wobbrock
2017 J jnl
IEEE Pervasive Comput.
Eun Kyoung Choe, Saeed Abdullah, Mashfiqui Rabbi, Edison Thomaz, Daniel A. Epstein, Felicia Cordeiro, Matthew Kay, Gregory D. Abowd, Tanzeem Choudhury, James Fogarty, Bongshin Lee, Mark Matthews, Julie A. Kientz
2017 A conf
CSCW
Jessica Schroeder, Jane Hoffswell, Chia-Fang Chung, James Fogarty, Sean Munson, Jasmine Zia
2017 A* conf
CHI
Ravi Karkar, Jessica Schroeder, Daniel A. Epstein, Laura R. Pina, Jeffrey Scofield, James Fogarty, Julie A. Kientz, Sean A. Munson, Roger Vilardaga, Jasmine Zia
2017 A* conf
CHI
Chia-Fang Chung, Elena Agapie, Jessica Schroeder, Sonali R. Mishra, James Fogarty, Sean A. Munson
2016 J jnl
J. Am. Medical Informatics Assoc.
Ravi Karkar, Jasmine Zia, Roger Vilardaga, Sonali R. Mishra, James Fogarty, Sean A. Munson, Julie A. Kientz
2016 A* conf
CHI
Daniel A. Epstein, Monica Caraway, Chuck Johnston, An Ping, James Fogarty, Sean A. Munson
2016 A* conf
CHI
Daniel A. Epstein, Felicia Cordeiro, James Fogarty, Gary Hsieh, Sean A. Munson
2016 A* conf
CHI
Xiaoyi Zhang, Laura R. Pina, James Fogarty
2016 Misc conf
UbiComp
Daniel A. Epstein, Jennifer H. Kang, Laura R. Pina, James Fogarty, Sean A. Munson
2016 conf
UbiComp Adjunct
Ravi Karkar, Rafal Kocielnik, Xiaoyi Zhang, James Fogarty, George N. Ioannou, Sean A. Munson, Jasmine Zia
2015 Misc conf
UbiComp
Daniel A. Epstein, An Ping, James Fogarty, Sean A. Munson
2015 A* conf
CHI
Felicia Cordeiro, Daniel A. Epstein, Edison Thomaz, Elizabeth S. Bales, Arvind Krishnaa Jagannathan, Gregory D. Abowd, James Fogarty
2015 A* conf
UIST
Donny Huang, Xiaoyi Zhang, T. Scott Saponas, James Fogarty, Shyamnath Gollakota
2015 conf
UbiComp/ISWC Adjunct
Ravi Karkar, James Fogarty, Julie A. Kientz, Sean A. Munson, Roger Vilardaga, Jasmine Zia
2015 A* conf
CHI
Felicia Cordeiro, Elizabeth S. Bales, Erin Cherry, James Fogarty
2014 B conf
AVI
Kyle Hipke, Michael Toomim, Rebecca Fiebrink, James Fogarty
2014 conf
UbiComp Adjunct
Daniel A. Epstein, James Fogarty, Sean A. Munson
2014 A* conf
CHI
Hao Lü, James Fogarty, Yang Li
2014 A* conf
UIST
Morgan Dixon, Alexander Conrad Nied, James Fogarty
2014 A conf
Conference on Designing Interactive Systems
Daniel A. Epstein, Felicia Cordeiro, Elizabeth S. Bales, James Fogarty, Sean A. Munson
2013 Misc conf
UbiComp
Daniel A. Epstein, Alan Borning, James Fogarty
2013 conf
PervasiveHealth
Adrienne H. Andrew, Gaetano Borriello, James Fogarty
2012 A* conf
CHI
Morgan Dixon, James Fogarty, Jacob O. Wobbrock
2012 J jnl
Pervasive Mob. Comput.
Eric C. Larson, Jon Froehlich, Tim Campbell, Conor Haggerty, Les E. Atlas, James Fogarty, Shwetak N. Patel
2012 A* conf
CHI
Saleema Amershi, James Fogarty, Daniel S. Weld
2012 J jnl
Inf. Polity
Sean A. Munson, Daniel Avrahami, Sunny Consolvo, James Fogarty, Batya Friedman, Ian E. Smith
2012 A* conf
UIST
Franziska Roesner, James Fogarty, Tadayoshi Kohno
2011 conf
Pervasive
Jon Froehlich, Eric C. Larson, Elliot Saba, Tim Campbell, Les E. Atlas, James Fogarty, Shwetak N. Patel
2011 C conf
FDG
Seth Cooper, Firas Khatib, Ilya Makedon, Hao Lü, Janos Barbero, David Baker, James Fogarty, Zoran Popovic, Foldit players
2011 conf
DG.O
Sean A. Munson, Daniel Avrahami, Sunny Consolvo, James Fogarty, Batya Friedman, Ian E. Smith
2011 A* conf
CHI
Morgan Dixon, Daniel Leventhal, James Fogarty
2011 A* conf
AAAI
Saleema Amershi, James Fogarty, Ashish Kapoor, Desney S. Tan
2011 B conf
VL/HCC
Ryder Ziola, Shweta Grampurohit, Nate Landes, James Fogarty, Beverly L. Harrison
2011 A* conf
IJCAI
Kayur Patel, Steven Mark Drucker, James Fogarty, Ashish Kapoor, Desney S. Tan
2010 conf
eScience
Keith Grochow, Mark Stoermer, James Fogarty, Charlotte Lee, Bill Howe, Edward D. Lazowska
2010 A* conf
CHI
Saleema Amershi, James Fogarty, Ashish Kapoor, Desney S. Tan
2010 A* conf
UIST
Kayur Patel, Naomi Bancroft, Steven Mark Drucker, James Fogarty, Amy J. Ko, James A. Landay
2010 A* conf
CHI
Morgan Dixon, James Fogarty
2010 conf
Pervasive
Evan Welbourne, Magdalena Balazinska, Gaetano Borriello, James Fogarty
2010 conf
DG.O
Travis Kriplean, Alan Borning, Paul Waddell, Christoffer Klang, James Fogarty
2009 A* conf
CHI
Katherine Everitt, Tanya Bragin, James Fogarty, Tadayoshi Kohno
2009 A* conf
CHI
Raphael Hoffmann, Saleema Amershi, Kayur Patel, Fei Wu, James Fogarty, Daniel S. Weld
2009 Misc conf
UbiComp
Jon Froehlich, Eric Larson, Tim Campbell, Conor Haggerty, James Fogarty, Shwetak N. Patel
2009 A conf
CIKM
Thomas Lin, Oren Etzioni, James Fogarty
2009 A* conf
UIST
Saleema Amershi, James Fogarty, Ashish Kapoor, Desney S. Tan
2009 A* conf
CHI
Jacob O. Wobbrock, James Fogarty, Shih-Yen (Sean) Liu, Shunichi Kimuro, Susumu Harada
2008 A* conf
CHI
Michael Toomim, Xianhang Zhang, James Fogarty, James A. Landay
2008 B conf
Graphics Interface
Hao Lü, James Fogarty
2008 A* conf
CHI
James Fogarty, Desney S. Tan, Ashish Kapoor, Simon A. J. Winder
2008 A* conf
AAAI
Kayur Patel, James Fogarty, James A. Landay, Beverly L. Harrison
2008 A conf
CSCW
Taj Campbell, Brian Ngo, James Fogarty
2008 A* conf
AAAI
Daniel S. Weld, Fei Wu, Eytan Adar, Saleema Amershi, James Fogarty, Raphael Hoffmann, Kayur Patel, Michael Skinner
2008 A* conf
CHI
Kayur Patel, James Fogarty, James A. Landay, Beverly L. Harrison
2008 A conf
ICWSM
Michael Toomim, Xianhang Zhang, James Fogarty, Nathan Morris
2008 B conf
ICMI
Susumu Harada, Jonathan Lester, Kayur Patel, T. Scott Saponas, James Fogarty, James A. Landay, Jacob O. Wobbrock
2008 A* conf
UIST
Eytan Adar, Mira Dontcheva, James Fogarty, Daniel S. Weld
2007 A* conf
UIST
Raphael Hoffmann, James Fogarty, Daniel S. Weld
2007 A* conf
CHI
Daniel Avrahami, James Fogarty, Scott E. Hudson
2007 A* conf
CHI
Joe Tullio, Anind K. Dey, Jason Chalecki, James Fogarty
2007 A* conf
CHI
James Fogarty, Scott E. Hudson
2007 B conf
PERSUASIVE
Adrienne H. Andrew, Gaetano Borriello, James Fogarty
2006 conf
WMCSA
Karen P. Tang, James Fogarty, Pedram Keyani, Jason I. Hong
2006 A* conf
CHI
Karen P. Tang, Pedram Keyani, James Fogarty, Jason I. Hong
2006 A* conf
UIST
James Fogarty, Carolyn Au, Scott E. Hudson
2005 B conf
Graphics Interface
James Fogarty, Ryan S. Baker, Scott E. Hudson
2005 A* conf
CHI
James Fogarty, Amy J. Ko, Htet Htet Aung, Elspeth Golden, Karen P. Tang, Scott E. Hudson
2005 J jnl
ACM Trans. Comput. Hum. Interact.
James Fogarty, Scott E. Hudson, Christopher G. Atkeson, Daniel Avrahami, Jodi Forlizzi, Sara B. Kiesler, Johnny C. Lee, Jie Yang
2004 A* conf
CHI
James Fogarty, Scott E. Hudson, Jennifer C. Lai
2004 J jnl
ACM Trans. Graph.
James Fogarty, Scott E. Hudson
2004 J jnl
Int. J. Hum. Comput. Stud.
James Fogarty, Jennifer C. Lai, Jim Christensen
2003 A* conf
UIST
James Fogarty, Scott E. Hudson
2003 B conf
Graphics Interface
James Fogarty, Jodi Forlizzi, Scott E. Hudson
2003 A* conf
CHI
Scott E. Hudson, James Fogarty, Christopher G. Atkeson, Daniel Avrahami, Jodi Forlizzi, Sara B. Kiesler, Johnny C. Lee, Jie Yang
2002 A* conf
UIST
James Fogarty, Jodi Forlizzi, Scott E. Hudson
2001 A* conf
UIST
James Fogarty, Jodi Forlizzi, Scott E. Hudson
2001 J jnl
Int. J. Hum. Comput. Stud.
John M. Carroll, Mary Beth Rosson, Philip L. Isenhour, Craig H. Ganoe, Dan Dunlap, James Fogarty, Wendy A. Schafer, Christina Van Metre
tests/unit/test_decompile_medium_level.py
← Index tests/unit/test_decompile_medium_level.py python
# tests/unit/test_decompile_medium_level.py
"""Unit tests (mocked BN) for bninja/analysis/medium_level.py
   and bninja/analysis/medium_level_normalization.py."""
# tests/unit/test_decompile_medium_level.py
import sys
from unittest.mock import MagicMock, patch

# Installa gli stubs BN
from tests.unit.conftest_binja_stubs import install_binja_stubs
install_binja_stubs()

# ── Definisci MockMLILInstruction PRIMA di importare il modulo ──
class MockMLILInstruction:
    def __init__(self, operation, address=0, operands=None):
        self.operation = operation
        self.address = address
        self.operands = operands or []

# ── Patcha il modulo BN in modo che isinstance() funzioni ──
sys.modules["binaryninja"].MediumLevelILInstruction = MockMLILInstruction
sys.modules["binaryninja"].SSAVariable = type("SSAVariable", (), {})
sys.modules["binaryninja"].Variable = type("Variable", (), {})
sys.modules["binaryninja"].ILIntrinsic = type("ILIntrinsic", (), {})

# Ora importa il modulo — vede già i tipi corretti
from redb.extractors.decompiler.bninja.analysis.medium_level_normalization import (
    MediumLevelNormalization,
)	

class MockMLILFunction:
    def __init__(self, instructions):
        self._instructions = instructions

    @property
    def instructions(self):
        return iter(self._instructions)

    @property
    def basic_blocks(self):
        # one block containing all instructions, good enough for MinHasher
        block = MagicMock()
        block.__iter__ = lambda self_: iter([])  # not used by MediumLevelAnalysis
        return [block]


class MockFunction:
    def __init__(self, name="func", start=0x1000, mlil=None):
        self.name = name
        self.start = start
        self.mlil = mlil



class TestMediumLevelNormalization:
    def setup_method(self):
        from redb.extractors.decompiler.bninja.analysis.medium_level_normalization import (
            MediumLevelNormalization,
        )
        self.norm = MediumLevelNormalization()

    def test_normalize_skeleton_single_instruction(self):
        il = MockMLILInstruction(operation=42, operands=[])
        result = self.norm.normalize_instruction_all_levels(il)
        assert result == [42]

    def test_normalize_skeleton_nested(self):
        inner = MockMLILInstruction(operation=7, operands=[])
        outer = MockMLILInstruction(operation=1, operands=[inner])
        result = self.norm.normalize_instruction_all_levels(outer)
        assert result == [1, 7]

    def test_normalize_skeleton_with_list_operand(self):
        inner_a = MockMLILInstruction(operation=10, operands=[])
        inner_b = MockMLILInstruction(operation=11, operands=[])
        outer = MockMLILInstruction(operation=2, operands=[[inner_a, inner_b]])
        result = self.norm.normalize_instruction_all_levels(outer)
        assert result == [2, 10, 11]

    def test_normalize_skeleton_none(self):
        result = self.norm.normalize_instruction_all_levels(None)
        # collect on None should leave ops empty
        assert result == []

    def test_normalize_typed_appends_leaf_types(self):
        # operand is a plain int -> "CONST"
        il = MockMLILInstruction(operation=3, operands=[42])
        result = self.norm.normalize_instr_with_operands(il)
        assert result == [3, "CONST"]

    def test_normalize_typed_bool_before_int(self):
        # bool must be detected before int (since bool is an int subclass)
        il = MockMLILInstruction(operation=4, operands=[True])
        result = self.norm.normalize_instr_with_operands(il)
        assert result == [4, "BOOL"]

    def test_normalize_typed_float(self):
        il = MockMLILInstruction(operation=5, operands=[1.5])
        result = self.norm.normalize_instr_with_operands(il)
        assert result == [5, "FLOAT_CONST"]

    def test_normalize_typed_str(self):
        il = MockMLILInstruction(operation=6, operands=["hello"])
        result = self.norm.normalize_instr_with_operands(il)
        assert result == [6, "STR"]

    def test_normalize_typed_unknown_falls_back_to_typename(self):
        class Weird:
            pass
        il = MockMLILInstruction(operation=8, operands=[Weird()])
        result = self.norm.normalize_instr_with_operands(il)
        assert result == [8, "WEIRD"]

    def test_normalize_typed_nested_mlil(self):
        inner = MockMLILInstruction(operation=99, operands=[7])
        outer = MockMLILInstruction(operation=1, operands=[inner])
        result = self.norm.normalize_instr_with_operands(outer)
        assert result == [1, 99, "CONST"]

    def test_normalize_typed_list_mixed(self):
        inner = MockMLILInstruction(operation=50, operands=[])
        il = MockMLILInstruction(operation=2, operands=[[inner, 99]])
        result = self.norm.normalize_instr_with_operands(il)
        assert result == [2, 50, "CONST"]


class TestMediumLevelAnalysis:
    def _make_analysis(self, instructions=None, mlil=True, start=0x1000):
        from redb.extractors.decompiler.bninja.analysis.medium_level import (
            MediumLevelAnalysis,
        )
        mlil_func = MockMLILFunction(instructions or []) if mlil else None
        func = MockFunction(name="testfunc", start=start, mlil=mlil_func)
        bv = MagicMock()
        return MediumLevelAnalysis(func, bv, MagicMock())

    def test_collect_returns_empty_when_no_mlil(self):
        a = self._make_analysis(mlil=False)
        sk, sk_addr, ty, ty_addr = a._collect_mlil_skeleton_and_typed()
        assert sk == [] and sk_addr == [] and ty == [] and ty_addr == []

    def test_collect_skeleton_and_typed_basic(self):
        instrs = [
            MockMLILInstruction(operation=1, address=0x1000, operands=[]),
            MockMLILInstruction(operation=2, address=0x1004, operands=[42]),
        ]
        a = self._make_analysis(instructions=instrs, start=0x1000)
        sk, sk_addr, ty, ty_addr = a._collect_mlil_skeleton_and_typed()

        assert sk == [[1], [2]]
        assert ty == [[1], [2, "CONST"]]
        assert sk_addr == [(0, [1]), (4, [2])]
        assert ty_addr == [(0, [1]), (4, [2, "CONST"])]

    def test_collect_negative_offset_clamped_to_zero(self):
        instrs = [
            MockMLILInstruction(operation=1, address=0x900, operands=[]),
        ]
        a = self._make_analysis(instructions=instrs, start=0x1000)
        _, sk_addr, _, ty_addr = a._collect_mlil_skeleton_and_typed()
        assert sk_addr[0][0] == 0
        assert ty_addr[0][0] == 0

    def test_log_error_records_entry(self):
        a = self._make_analysis()
        a.log_error("boom", "fname", 0x1234, ValueError("x"), "loc")
        assert len(a.errors) == 1
        err = a.errors[0]
        assert err["function_name"] == "fname"
        assert err["function_address"] == "4660"  # hex 0x1234
        assert err["error_location"] == "loc"
        assert err["error_message"] == "boom"
        assert err["error_type"] == "ValueError"
        assert "timestamp" in err

    @patch(
        "redb.extractors.decompiler.bninja.analysis.medium_level.MinHasher"
    )
    def test_analyze_returns_expected_keys(self, mock_minhasher):
        mock_minhasher.return_value.calculateMinHash.return_value = [1, 2, 3]

        instrs = [
            MockMLILInstruction(operation=1, address=0x1000, operands=[]),
            MockMLILInstruction(operation=2, address=0x1004, operands=[42]),
            MockMLILInstruction(operation=3, address=0x1008, operands=[]),
        ]
        a = self._make_analysis(instructions=instrs, start=0x1000)
        result, errors = a.analyze()

        expected_keys = {
            "function_address",
            "body_mlil_skeleton_vector",
            "sha256_mlil_skeleton",
            "tlsh_mlil_skeleton",
            "minhash_mlil_skeleton",
            "body_mlil_typed_vector",
            "sha256_mlil_typed",
            "tlsh_mlil_typed",
            "minhash_mlil_typed",
        }
        assert set(result.keys()) == expected_keys
        assert result["function_address"] == 0x1000
        assert result["minhash_mlil_skeleton"] == [1, 2, 3]
        assert result["minhash_mlil_typed"] == [1, 2, 3]
        assert errors == []

    @patch(
        "redb.extractors.decompiler.bninja.analysis.medium_level.MinHasher"
    )
    def test_analyze_empty_mlil(self, mock_minhasher):
        mock_minhasher.return_value.calculateMinHash.return_value = []
        a = self._make_analysis(mlil=False)
        result, errors = a.analyze()
        assert result["body_mlil_skeleton_vector"] == []
        assert result["body_mlil_typed_vector"] == []
        assert errors == []

    @patch(
        "redb.extractors.decompiler.bninja.analysis.medium_level.MinHasher"
    )
    def test_analyze_sha256_differs_skeleton_vs_typed(self, mock_minhasher):
        mock_minhasher.return_value.calculateMinHash.return_value = []

        instrs = [
            MockMLILInstruction(operation=1, address=0x1000, operands=[42]),
            MockMLILInstruction(operation=2, address=0x1004, operands=["foo"]),
            MockMLILInstruction(operation=3, address=0x1008, operands=[True]),
        ]
        a = self._make_analysis(instructions=instrs)
        result, _ = a.analyze()
        # skeleton ignores operand leaves, typed includes them -> different hashes
        assert result["sha256_mlil_skeleton"] != result["sha256_mlil_typed"]


class TestMinHasherMLILKinds:
    def _make_func(self, instrs):
        # MinHasher iterates basic_blocks then over each block
        block = MagicMock()
        block.__iter__ = lambda self_: iter(instrs)
        f = MagicMock()
        f.basic_blocks = [block]
        return f

    def test_mlil_skeleton_uses_medium_normalizer(self):
        from redb.extractors.decompiler.bninja.similarity.minhasher import (
            MinHasher, TokenKind,
        )
        instrs = [
            MockMLILInstruction(operation=i, operands=[]) for i in range(5)
        ]
        func = self._make_func(instrs)
        hasher = MinHasher(seed=42, il_function=func, kind=TokenKind.MLIL)
        result = hasher.calculateMinHash()
        # 5 instructions -> 3 trigrams -> non-empty signature
        assert result != []

    def test_typed_mlil_differs_from_skeleton(self):
        from redb.extractors.decompiler.bninja.similarity.minhasher import (
            MinHasher, TokenKind,
        )
        instrs = [
            MockMLILInstruction(operation=1, operands=[42]),
            MockMLILInstruction(operation=2, operands=["s"]),
            MockMLILInstruction(operation=3, operands=[True]),
            MockMLILInstruction(operation=4, operands=[1.5]),
        ]
        func = self._make_func(instrs)
        skel = MinHasher(seed=42, il_function=func, kind=TokenKind.MLIL).calculateMinHash()
        typed = MinHasher(seed=42, il_function=func, kind=TokenKind.TYPED_MLIL).calculateMinHash()
        # Same seed, same instructions, but typed has extra leaf tokens
        # -> hashes should generally differ
        assert skel != typed

    def test_mlil_too_few_instructions(self):
        from redb.extractors.decompiler.bninja.similarity.minhasher import (
            MinHasher, TokenKind,
        )
        instrs = [MockMLILInstruction(operation=1, operands=[])] * 2
        func = self._make_func(instrs)
        hasher = MinHasher(seed=42, il_function=func, kind=TokenKind.MLIL)
        assert hasher.calculateMinHash() == []

    def test_unsupported_kind_raises(self):
        from redb.extractors.decompiler.bninja.similarity.minhasher import MinHasher
        func = self._make_func([])
        hasher = MinHasher(seed=42, il_function=func, kind="bogus")
        with pytest.raises(ValueError):
            hasher.calculateMinHash()