Mads Nielsen

243 papers A* 3A 7B 29C 2Misc 1Journal 92Unranked 95
YearRankTypeTitle / Venue / Authors
2025 J jnl
CoRR
William Michael Laprade, Jesper Cairo Westergaard, Svend Christensen, Mads Nielsen, Anders Bjorholm Dahl
2025 J jnl
CoRR
Asbjørn Munk, Stefano Cerri, Jakob Ambsdorf, Julia Machnio, Sebastian Nørgaard Llambias, Vardan Nersesjan, Christian Hedeager Krag, Peirong Liu, Pablo Rocamora-García, Mostafa Mehdipour-Ghazi, Mikael Boesen, Michael Eriksen Benros, Juan Eugenio Iglesias, Mads Nielsen
2025 conf
SCIA (1)
Sebastian Nørgaard Llambias, Mads Nielsen, Mostafa Mehdipour-Ghazi
2025 conf
NLDL
Julia Machnio, Mads Nielsen, Mostafa Mehdipour-Ghazi
2025 J jnl
CoRR
Julia Machnio, Mads Nielsen, Mostafa Mehdipour-Ghazi
2025 conf
SCIA (1)
Mostafa Mehdipour-Ghazi, Mads Nielsen
2025 conf
MICCAI (7)
Jakob Ambsdorf, Asbjørn Munk, Sebastian Nørgaard Llambias, Anders Nymark Christensen, Kamil Wojciech Mikolaj, Randall Balestriero, Martin Grønnebæk Tolsgaard, Aasa Feragen, Mads Nielsen
2025 J jnl
CoRR
Jakob Ambsdorf, Asbjørn Munk, Sebastian Nørgaard Llambias, Anders Nymark Christensen, Kamil Wojciech Mikolaj, Randall Balestriero, Martin Grønnebæk Tolsgaard, Aasa Feragen, Mads Nielsen
2025 J jnl
npj Digit. Medicine
Kamil Wojciech Mikolaj, Anders Nymark Christensen, Caroline Taksøe-Vester, Aasa Feragen, Olav Bjørn Petersen, Manxi Lin, Mads Nielsen, Morten Bo Søndergaard Svendsen, Martin Grønnebæk Tolsgaard
2025 J jnl
CoRR
Jakob Krogh Petersen, Valdemar Licht, Mads Nielsen, Asbjørn Munk
2025 conf
ISBI
Jakob Krogh Petersen, Valdemar Licht, Mads Nielsen, Asbjørn Munk
2025 conf
MICCAI (5)
Ao Ma, Qingpeng Zhu, Jingjing Li, Mads Nielsen, Xu Chen
2025 J jnl
CoRR
Julia Machnio, Mads Nielsen, Mostafa Mehdipour-Ghazi
2025 J jnl
CoRR
Julia Machnio, Sebastian Nørgaard Llambias, Mads Nielsen, Mostafa Mehdipour-Ghazi
2024 J jnl
CoRR
Asbjørn Munk, Jakob Ambsdorf, Sebastian Nørgaard Llambias, Mads Nielsen
2024 J jnl
CoRR
Milla E. Nielsen, Mads Nielsen, Mostafa Mehdipour-Ghazi
2024 J jnl
IEEE Trans. Neural Networks Learn. Syst.
Mostafa Mehdipour-Ghazi, Lauge Sørensen, Sébastien Ourselin, Mads Nielsen
2024 conf
MLHC
Mikkel Odgaard, Kiril Vadimovic Klein, Martin Sillesen, Sanne Møller Thysen, Espen Jimenez-Solem, Mads Nielsen
2024 J jnl
CoRR
Mikkel Odgaard, Kiril Vadimovic Klein, Sanne Møller Thysen, Espen Jimenez-Solem, Martin Sillesen, Mads Nielsen
2024 conf
NLDL
Sebastian Nørgaard Llambias, Mads Nielsen, Mostafa Mehdipour-Ghazi
2024 conf
CVPR Workshops
William Michael Laprade, Pawel Tomasz Pieta, Svetlana Kutuzova, Jesper Cairo Westergaard, Mads Nielsen, Svend Christensen, Anders Bjorholm Dahl
2024 conf
ISBI
Manxi Lin, Jakob Ambsdorf, Emilie Pi Fogtmann Sejer, Zahra Bashir, Chun Kit Wong, Paraskevas Pegios, Alberto Raheli, Morten Bo Søndergaard Svendsen, Mads Nielsen, Martin Grønnebæk Tolsgaard, Anders Nymark Christensen, Aasa Feragen
2024 J jnl
CoRR
Manxi Lin, Jakob Ambsdorf, Emilie Pi Fogtmann Sejer, Zahra Bashir, Chun Kit Wong, Paraskevas Pegios, Alberto Raheli, Morten Bo Søndergaard Svendsen, Mads Nielsen, Martin Grønnebæk Tolsgaard, Anders Nymark Christensen, Aasa Feragen
2024 conf
NLDL
Jon Middleton, Marko Bauer, Kaining Sheng, Jacob Johansen, Mathias Perslev, Silvia Ingala, Mads Nielsen, Akshay Pai
2024 J jnl
CoRR
Jon Middleton, Marko Bauer, Kaining Sheng, Jacob Johansen, Mathias Perslev, Silvia Ingala, Mads Nielsen, Akshay Pai
2024 conf
NLDL
Asbjørn Munk, Mads Nielsen
2024 conf
ASMUS@MICCAI
Markus Ditlev Sjøgren Olsen, Jakob Ambsdorf, Manxi Lin, Caroline Taksøe-Vester, Morten Bo Søndergaard Svendsen, Anders Nymark Christensen, Mads Nielsen, Martin Grønnebæk Tolsgaard, Aasa Feragen, Paraskevas Pegios
2024 J jnl
CoRR
Markus Ditlev Sjøgren Olsen, Jakob Ambsdorf, Manxi Lin, Caroline Taksøe-Vester, Morten Bo Søndergaard Svendsen, Anders Nymark Christensen, Mads Nielsen, Martin Grønnebæk Tolsgaard, Aasa Feragen, Paraskevas Pegios
2024 J jnl
CoRR
Sebastian Nørgaard Llambias, Julia Machnio, Asbjørn Munk, Jakob Ambsdorf, Mads Nielsen, Mostafa Mehdipour-Ghazi
2023 conf
MILLanD@MICCAI
Ji Wu, Zhongfeng Kang, Sebastian Nørgaard Llambias, Mostafa Mehdipour-Ghazi, Mads Nielsen
2023 conf
SCIA (2)
William Michael Laprade, Jesper Cairo Westergaard, Jon Nielsen, Mads Nielsen, Anders Bjorholm Dahl
2023 J jnl
CoRR
Sebastian Nørgaard Llambias, Mads Nielsen, Mostafa Mehdipour-Ghazi
2023 conf
ISBI
Neus Rodeja Ferrer, Malini Vendela Sagar, Kiril Vadimovic Klein, Christina Kruuse, Mads Nielsen, Mostafa Mehdipour-Ghazi
2023 J jnl
CoRR
Neus Rodeja Ferrer, Malini Vendela Sagar, Kiril Vadimovic Klein, Christina Kruuse, Mads Nielsen, Mostafa Mehdipour-Ghazi
2023 conf
ASMUS@MICCAI
Paraskevas Pegios, Emilie Pi Fogtmann Sejer, Manxi Lin, Zahra Bashir, Morten Bo Søndergaard Svendsen, Mads Nielsen, Eike Petersen, Anders Nymark Christensen, Martin Grønnebæk Tolsgaard, Aasa Feragen
2023 J jnl
CoRR
Asbjørn Munk, Ao Ma, Mads Nielsen
2023 J jnl
Expert Syst. Appl.
Zhongfeng Kang, Mads Nielsen, Bo Yang, Lihui Deng, Stephan Sloth Lorenzen
2023 J jnl
Inf. Fusion
Zhongfeng Kang, Mads Nielsen, Bo Yang, Mostafa Mehdipour-Ghazi
2022 J jnl
Neurocomputing
Zhongfeng Kang, Bo Yang, Mads Nielsen, Lihui Deng, Shantian Yang
2022 J jnl
CoRR
Mauricio Orbes-Arteaga, Thomas Varsavsky, Lauge Sørensen, Mads Nielsen, Akshay Pai, Sébastien Ourselin, Marc Modat, M. Jorge Cardoso
2022 J jnl
CoRR
Mostafa Mehdipour-Ghazi, Mads Nielsen
2022 A* conf
ICLR
Stephan Sloth Lorenzen, Christian Igel, Mads Nielsen
2022 conf
MAD@MICCAI
Jon Middleton, Marko Bauer, Jacob Johansen, Mads Nielsen, Stefan Sommer, Akshay Pai
2022 J jnl
CoRR
Andreas D. Lauritzen, My Catarina von Euler-Chelpin, Elsebeth Lynge, Ilse Vejborg, Mads Nielsen, Nico Karssemeijer, Martin Lillholm
2021 J jnl
CoRR
Mostafa Mehdipour-Ghazi, Lauge Sørensen, Sébastien Ourselin, Mads Nielsen
2021 J jnl
CoRR
Stephan Sloth Lorenzen, Christian Igel, Mads Nielsen
2021 ed.
IPMI
Aasa Feragen, Stefan Sommer, Julia A. Schnabel, Mads Nielsen
2021 B conf
Image Processing
Irme Groothuis, Carole H. Sudre, Silvia Ingala, Josephine Barnes, Juan Domingo Gispert, Lauge Sørensen, Akshay Pai, Mads Nielsen, Sébastien Ourselin, M. Jorge Cardoso, Frederik Barkhof, Marc Modat
2021 J jnl
CoRR
Svetlana Kutuzova, Oswin Krause, Douglas McCloskey, Mads Nielsen, Christian Igel
2021 J jnl
NeuroImage
Mostafa Mehdipour-Ghazi, Mads Nielsen, Akshay Pai, Marc Modat, M. Jorge Cardoso, Sébastien Ourselin, Lauge Sørensen
2020 J jnl
CoRR
Raghavendra Selvan, Erik B. Dam, Sofus Rischel, Kaining Sheng, Mads Nielsen, Akshay Pai
2020 J jnl
Medical Image Anal.
Hayit Greenspan, Raúl San José Estépar, Wiro J. Niessen, Eliot L. Siegel, Mads Nielsen
2019 J jnl
IEEE Trans. Medical Imaging
Jens Petersen, Andrés M. Arias Lorza, Raghavendra Selvan, Daniel Bos, Aad van der Lugt, Jesper Johannes Holst Pedersen, Mads Nielsen, Marleen de Bruijne
2019 conf
OR/MLCN@MICCAI
Mauricio Orbes-Arteaga, M. Jorge Cardoso, Lauge Sørensen, Christian Igel, Sébastien Ourselin, Marc Modat, Mads Nielsen, Akshay Pai
2019 J jnl
CoRR
Mauricio Orbes-Arteaga, M. Jorge Cardoso, Lauge Sørensen, Christian Igel, Sébastien Ourselin, Marc Modat, Mads Nielsen, Akshay Pai
2019 J jnl
CoRR
Mauricio Orbes-Arteaga, Thomas Varsavsky, Carole H. Sudre, Zach Eaton-Rosen, Lewis J. Haddow, Lauge Sørensen, Mads Nielsen, Akshay Pai, Sébastien Ourselin, Marc Modat, Parashkev Nachev, Manuel Jorge Cardoso
2019 conf
DART/MIL3ID@MICCAI
Mauricio Orbes-Arteaga, Thomas Varsavsky, Carole H. Sudre, Zach Eaton-Rosen, Lewis J. Haddow, Lauge Sørensen, Mads Nielsen, Akshay Pai, Sébastien Ourselin, Marc Modat, Parashkev Nachev, M. Jorge Cardoso
2019 ed.
MBIA/MFCA@MICCAI
Dajiang Zhu, Jingwen Yan, Heng Huang, Li Shen, Paul M. Thompson, Carl-Fredrik Westin, Xavier Pennec, Sarang C. Joshi, Mads Nielsen, Tom Fletcher, Stanley Durrleman, Stefan Sommer
2019 conf
ICONIP (1)
Mostafa Mehdipour-Ghazi, Mads Nielsen, Akshay Pai, Marc Modat, M. Jorge Cardoso, Sébastien Ourselin, Lauge Sørensen
2019 J jnl
CoRR
Mostafa Mehdipour-Ghazi, Mads Nielsen, Akshay Pai, Marc Modat, M. Jorge Cardoso, Sébastien Ourselin, Lauge Sørensen
2019 B conf
Image Processing
Mauricio Orbes-Arteaga, Lauge Sørensen, Manuel Jorge Cardoso, Marc Modat, Sébastien Ourselin, Stefan Sommer, Mads Nielsen, Christian Igel, Akshay Pai
2019 J jnl
CoRR
Mostafa Mehdipour-Ghazi, Mads Nielsen, Akshay Pai, Marc Modat, M. Jorge Cardoso, Sébastien Ourselin, Lauge Sørensen
2019 J jnl
Medical Image Anal.
Mostafa Mehdipour-Ghazi, Mads Nielsen, Akshay Pai, M. Jorge Cardoso, Marc Modat, Sébastien Ourselin, Lauge Sørensen
2019 J jnl
CoRR
Mostafa Mehdipour-Ghazi, Mads Nielsen, Akshay Pai, M. Jorge Cardoso, Marc Modat, Sébastien Ourselin, Lauge Sørensen
2018 J jnl
CoRR
François Lauze, Mads Nielsen
2018 J jnl
CoRR
Mauricio Orbes-Arteaga, Lauge Sørensen, Manuel Jorge Cardoso, Marc Modat, Sébastien Ourselin, Stefan Sommer, Mads Nielsen, Christian Igel, Akshay Pai
2018 J jnl
CoRR
Mostafa Mehdipour-Ghazi, Mads Nielsen, Akshay Pai, M. Jorge Cardoso, Marc Modat, Sébastien Ourselin, Lauge Sørensen
2018 J jnl
CoRR
Mauricio Orbes-Arteaga, M. Jorge Cardoso, Lauge Sørensen, Marc Modat, Sébastien Ourselin, Mads Nielsen, Akshay Pai
2017 J jnl
CoRR
Akshay Pai, Stefan Sommer, Lars Lau Rakêt, Line Kühnel, Sune Darkner, Lauge Sørensen, Mads Nielsen
2017 ch.
Deep Learning for Medical Image Analysis
Akshay Pai, Yuan-Ching Teng, Joseph Blair, Michiel Kallenberg, Erik B. Dam, Stefan Sommer, Christian Igel, Mads Nielsen
2017 conf
SCIA (1)
Malte Stær Nissen, Oswin Krause, Kristian Almstrup, Søren Kjærulff, Torben Trindkær Nielsen, Mads Nielsen
2017 J jnl
CoRR
Malte Stær Nissen, Oswin Krause, Kristian Almstrup, Søren Kjærulff, Torben Trindkær Nielsen, Mads Nielsen
2017 ed.
GRAIL/MFCA/MICGen@MICCAI
M. Jorge Cardoso, Tal Arbel, Enzo Ferrante, Xavier Pennec, Adrian V. Dalca, Sarah Parisot, Sarang C. Joshi, Nematollah Kayhan Batmanghelich, Aristeidis Sotiras, Mads Nielsen, Mert R. Sabuncu, Tom Fletcher, Li Shen, Stanley Durrleman, Stefan Sommer
2016 conf
MCV/BAMBI@MICCAI
Akshay Pai, Stefan Sommer, Lars Lau Rakêt, Line Kühnel, Sune Darkner, Lauge Sørensen, Mads Nielsen
2016 B conf
Image Processing
Mateusz Michalkiewicz, Akshay Pai, Kelvin K. Leung, Stefan Sommer, Sune Darkner, Lauge Sørensen, Jon Sporring, Mads Nielsen
2016 J jnl
IEEE Trans. Medical Imaging
Akshay Pai, Stefan Sommer, Lauge Sørensen, Sune Darkner, Jon Sporring, Mads Nielsen
2016 conf
Digital Mammography / IWDM
Michiel Kallenberg, Mads Nielsen, Katharina Holland, Nico Karssemeijer, Christian Igel, Martin Lillholm
2016 B conf
Image Processing
Niklas Kasenburg, Matthew G. Liptrot, Nina Linde Reislev, Ellen Garde, Mads Nielsen, Aasa Feragen
2016 J jnl
NeuroImage
Niklas Kasenburg, Matthew G. Liptrot, Nina Linde Reislev, Silas N. Ørting, Mads Nielsen, Ellen Garde, Aasa Feragen
2016 J jnl
IEEE Trans. Medical Imaging
Michiel Kallenberg, Kersten Petersen, Mads Nielsen, Andrew Y. Ng, Pengfei Diao, Christian Igel, Celine M. Vachon, Katharina Holland, Rikke Rass Winkel, Nico Karssemeijer, Martin Lillholm
2015 conf
ISBI
Akshay Pai, Stefan Klein, Stefan Sommer, Sune Darkner, Jon Sporring, Mads Nielsen
2015 B conf
Image Processing
Akshay Pai, Stefan Sommer, Lauge Sørensen, Sune Darkner, Jon Sporring, Mads Nielsen
2015 conf
MICCAI (2)
Henrik G. Jensen, François Lauze, Mads Nielsen, Sune Darkner
2014 J jnl
BMC Medical Imaging
Lene Lillemark, Lauge Sørensen, Akshay Pai, Erik B. Dam, Mads Nielsen
2014 conf
Digital Mammography / IWDM
Kersten Petersen, Mads Nielsen, Pengfei Diao, Nico Karssemeijer, Martin Lillholm
2014 J jnl
J. Math. Imaging Vis.
Aasa Feragen, Mads Nielsen, Eva Bjørn Vedel Jensen, Andrew du Plessis, François Lauze
2014 J jnl
Medical Image Anal.
Jens Petersen, Mads Nielsen, Pechin Lo, Lars Haug Nordenmark, Jesper Johannes Holst Pedersen, Mathilde Marie Winkler Wille, Asger Dirksen, Marleen de Bruijne
2014 J jnl
Adv. Comput. Math.
Stefan Sommer, François Lauze, Mads Nielsen
2014 conf
WBIR
Akshay Pai, Stefan Sommer, Sune Darkner, Lauge Sørensen, Jon Sporring, Mads Nielsen
2013 J jnl
Mach. Vis. Appl.
Peter Mysling, Kersten Petersen, Mads Nielsen, Martin Lillholm
2013 conf
ISBI
Akshay Pai, Lauge Sørensen, Sune Darkner, Peter Mysling, Dan R. Jørgensen, Erik B. Dam, Martin Lillholm, Joonmi Oh, Gennan Chen, Joyce Suhy, Jon Sporring, Mads Nielsen
2013 conf
MICCAI (2)
Adhish Prasoon, Kersten Petersen, Christian Igel, François Lauze, Erik Dam, Mads Nielsen
2013 conf
EMBC
Adhish Prasoon, Christian Igel, Marco Loog, François Lauze, Erik B. Dam, Mads Nielsen
2013 J jnl
SIAM J. Imaging Sci.
Stefan Sommer, Mads Nielsen, Sune Darkner, Xavier Pennec
2013 J jnl
Int. J. Comput. Vis.
Xavier Pennec, Sarang C. Joshi, Mads Nielsen
2013 B conf
Image Processing
Lene Lillemark, Lauge Sørensen, Peter Mysling, Akshay Pai, Erik B. Dam, Mads Nielsen
2013 J jnl
J. Math. Imaging Vis.
Stefan Sommer, François Lauze, Mads Nielsen, Xavier Pennec
2013 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Aasa Feragen, Pechin Lo, Marleen de Bruijne, Mads Nielsen, François Lauze
2012 J jnl
IEEE Trans. Medical Imaging
Kersten Petersen, Melanie Ganz, Peter Mysling, Mads Nielsen, Lene Lillemark, Alessandro Crimi, Sami S. Brandt
2012 B conf
ICPR
Lars Lau Rakêt, Mads Nielsen
2012 J jnl
IEEE Trans. Medical Imaging
Sudhakar Tummala, Mads Nielsen, Martin Lillholm, Claus Christiansen, Erik B. Dam
2012 B conf
Image Processing
Adhish Prasoon, Christian Igel, Marco Loog, François Lauze, Erik Dam, Mads Nielsen
2012 J jnl
Int. J. Biomed. Imaging
Melanie Ganz, Marleen de Bruijne, Erik B. Dam, Paola Pettersen, Morten Asser Karsdal, Claus Christiansen, Mads Nielsen
2012 conf
Digital Mammography / IWDM
Gopal Karemore, Brad M. Keller, Huen Oh, Julia Tchou, Mads Nielsen, Emily F. Conant, Despina Kontos
2012 J jnl
Medical Image Anal.
Vladlena Gorbunova, Jon Sporring, Pechin Lo, Martine Loeve, Harm A. Tiddens, Mads Nielsen, Asger Dirksen, Marleen de Bruijne
2012 B conf
ICPR
Konstantin Chernoff, Marco Loog, Mads Nielsen
2012 conf
MMBIA
Stefan Sommer, Mads Nielsen, Xavier Pennec
2012 J jnl
IEEE Trans. Medical Imaging
Lauge Sørensen, Mads Nielsen, Pechin Lo, Haseem Ashraf, Jesper Johannes Holst Pedersen, Marleen de Bruijne
2012 J jnl
CoRR
Aasa Feragen, Pechin Lo, Marleen de Bruijne, Mads Nielsen, François Lauze
2012 conf
Computer-Aided Diagnosis
C. Chen, Lauge Sørensen, François Lauze, Christian Igel, Marco Loog, Aasa Feragen, Marleen de Bruijne, Mads Nielsen
2011 conf
IPMI
Stefan Sommer, Mads Nielsen, François Lauze, Xavier Pennec
2011 J jnl
IEEE Trans. Medical Imaging
Sami S. Brandt, Gopal Karemore, Nico Karssemeijer, Mads Nielsen
2011 conf
MLMI
Peter Mysling, Kersten Petersen, Mads Nielsen, Martin Lillholm
2011 conf
ICCV Workshops
Aditya Tatu, François Lauze, Mads Nielsen, Benjamin B. Kimia
2011 J jnl
CoRR
Stefan Sommer, Mads Nielsen, Sune Darkner, Xavier Pennec
2011 conf
SSVM
Stefan Sommer, François Lauze, Mads Nielsen, Xavier Pennec
2011 J jnl
IEEE Trans. Medical Imaging
Alessandro Crimi, Martin Lillholm, Mads Nielsen, Anarta Ghosh, Marleen de Bruijne, Erik B. Dam, Jon Sporring
2011 A* conf
ICCV
Aasa Feragen, Søren Hauberg, Mads Nielsen, François Lauze
2011 C conf
MMSP
Xin Huang, Lars Lau Rakêt, Huynh Van Luong, Mads Nielsen, François Lauze, Søren Forchhammer
2011 conf
IPMI
Jens Petersen, Mads Nielsen, Pechin Lo, Zaigham Saghir, Asger Dirksen, Marleen de Bruijne
2011 conf
EMMCVPR
Lars Lau Rakêt, Lars Roholm, Mads Nielsen, François Lauze
2011 conf
ACPR
Chen Chen, François Lauze, Christian Igel, Aasa Feragen, Marco Loog, Mads Nielsen
2011 J jnl
IEEE Trans. Image Process.
Sune Høgild Keller, François Lauze, Mads Nielsen
2010 conf
ECCV (4)
Kersten Petersen, Mads Nielsen, Sami S. Brandt
2010 J jnl
Medical Image Anal.
Arish A. Qazi, Dan R. Jørgensen, Martin Lillholm, Marco Loog, Mads Nielsen, Erik B. Dam
2010 B conf
Image Processing
Chen Chen, Konstantin Chernoff, Gopal Karemore, Pechin Lo, Mads Nielsen, François Lauze
2010 conf
MCV
Kersten Petersen, Mads Nielsen, Sami S. Brandt
2010 conf
MICCAI (2)
Vladlena Gorbunova, Sander S. A. M. Jacobs, Pechin Lo, Asger Dirksen, Mads Nielsen, Alireza Bab-Hadiashar, Marleen de Bruijne
2010 B conf
ICPR
Aasa Feragen, François Lauze, Mads Nielsen
2010 conf
ACCV (2)
Aasa Feragen, François Lauze, Pechin Lo, Marleen de Bruijne, Mads Nielsen
2010 conf
Computer-Aided Diagnosis
Melanie Ganz, Marleen de Bruijne, Mads Nielsen
2010 conf
ECCV (6)
Stefan Sommer, François Lauze, Søren Hauberg, Mads Nielsen
2010 J jnl
J. Math. Imaging Vis.
Aditya Tatu, François Lauze, Stefan Sommer, Mads Nielsen
2010 conf
MLMI
Melanie Ganz, Mads Nielsen, Sami S. Brandt
2010 conf
Computer-Aided Diagnosis
Jens Petersen, Pechin Lo, Mads Nielsen, Goutham Edula, Haseem Ashraf, Asger Dirksen, Marleen de Bruijne
2010 J jnl
CoRR
Stefan Sommer, François Lauze, Mads Nielsen
2010 B conf
ICPR
Konstantin Chernoff, Mads Nielsen
2009 conf
VISAPP (2)
David Gustavsson, Kim Steenstrup Pedersen, Mads Nielsen
2009 B conf
Image Processing
Alessandro Crimi, Anarta Ghosh, Jon Sporring, Mads Nielsen
2009 conf
CVPR Workshops
Stefan Sommer, Aditya Tatu, Chen Chen, D. R. Jurgensen, Marleen de Bruijne, Marco Loog, Mads Nielsen, François Lauze
2009 conf
CVPR Workshops
Melanie Ganz, Marco Loog, Sami S. Brandt, Mads Nielsen
2009 J jnl
Int. J. Comput. Vis.
Mads Nielsen, Wiro J. Niessen, Carl-Fredrik Westin
2009 conf
Computer-Aided Diagnosis
Gopal Karemore, Mads Nielsen
2009 conf
MICCAI (1)
Lauge Sørensen, Pechin Lo, Haseem Ashraf, Jon Sporring, Mads Nielsen, Marleen de Bruijne
2009 B conf
Image Processing
Vladlena Gorbunova, Pechin Lo, Martine Loeve, Harm A. Tiddens, Jon Sporring, Mads Nielsen, Marleen de Bruijne
2009 conf
SSVM
David Gustavsson, Kim Steenstrup Pedersen, François Lauze, Mads Nielsen
2009 conf
IPMI
Konstantin Chernoff, Mads Nielsen
2009 conf
Computer-Aided Diagnosis
Naga P. K. R. Dandu, Mads Nielsen
2008 B conf
Image Processing
Arish A. Qazi, Erik B. Dam, Marco Loog, Mads Nielsen, François Lauze, Claus Christiansen
2008 J jnl
IEEE Trans. Medical Imaging
Jakob Raundahl, Marco Loog, Paola Pettersen, László B. Tankó, Mads Nielsen
2008 J jnl
J. Math. Imaging Vis.
Mads Nielsen, Peter Johansen, Andrew D. Jackson, Benny Lautrup, Søren Hauberg
2008 C conf
BIBE
Gopal Karemore, Mads Nielsen, Kim Komal Mascarenhas, K. S. Choudhary, Ajeethkumar Patil, V. K. Unnikrishnan, Vijendra Prabhu, Arunkumar Chowla, C. Santhosh
2008 J jnl
IEEE Trans. Image Process.
Sune Høgild Keller, François Lauze, Mads Nielsen
2008 J jnl
J. Math. Imaging Vis.
Anne Cuzol, Kim Steenstrup Pedersen, Mads Nielsen
2008 J jnl
Int. J. Comput. Vis.
François Lauze, Mads Nielsen
2008 conf
VISAPP (1)
Ketut Fundana, Niels Chr. Overgaard, Anders Heyden, David Gustavsson, Mads Nielsen
2008 J jnl
J. Math. Imaging Vis.
Mads Nielsen, Marleen de Bruijne, Camilla Jørgensen, Søren I. Olsen, Kim Steenstrup Pedersen, Jon Sporring
2008 conf
MICCAI (2)
Vladlena Gorbunova, Pechin Lo, Haseem Ashraf, Asger Dirksen, Mads Nielsen, Marleen de Bruijne
2007 conf
MICCAI (2)
Juan Eugenio Iglesias, Marleen de Bruijne, Marco Loog, François Lauze, Mads Nielsen
2007 B conf
Image Processing
Arish A. Qazi, Erik B. Dam, Ole Fogh Olsen, Mads Nielsen, Claus Christiansen
2007 conf
SSVM
Aditya Tatu, François Lauze, Mads Nielsen, Ole Fogh Olsen
2007 J jnl
Medical Image Anal.
David J. Hawkes, Mads Nielsen
2007 B conf
Image Processing
Mads Nielsen
2007 B conf
Image Processing
Jakob Raundahl, Marco Loog, Paola Pettersen, Mads Nielsen
2007 conf
SCIA
David Gustavsson, Kim Steenstrup Pedersen, Mads Nielsen
2007 conf
SSVM
Sune Høgild Keller, François Lauze, Mads Nielsen
2007 conf
MICCAI (2)
Lars A. Conrad-Hansen, Marleen de Bruijne, François Lauze, László B. Tankó, Paola Pettersen, Qing He, Jianghong Chen, Claus Christiansen, Mads Nielsen
2007 conf
MICCAI (2)
Jakob Raundahl, Marco Loog, Paola Pettersen, Mads Nielsen
2007 J jnl
Medical Image Anal.
Marleen de Bruijne, Michael T. Lund, László B. Tankó, Paola Pettersen, Mads Nielsen
2007 conf
Computer-Aided Diagnosis
Lars A. Conrad-Hansen, Marleen de Bruijne, Mads Nielsen, Maria Petrou
2007 B conf
Image Processing
Marleen de Bruijne, Paola C. Pettersen, László B. Tankó, Mads Nielsen
2006 B conf
Image Processing
Lars A. Conrad-Hansen, Marleen de Bruijne, François Lauze, László B. Tankó, Mads Nielsen
2006 J jnl
J. Math. Imaging Vis.
Arjan Kuijper, Ole Fogh Olsen, Peter J. Giblin, Mads Nielsen
2006 ch.
Handbook of Mathematical Models in Computer Vision
Mads Nielsen, Bo Markussen
2006 B conf
Image Processing
Jakob Raundahl, Marco Loog, Mads Nielsen
2006 ed.
MICCAI (1)
Rasmus Larsen, Mads Nielsen, Jon Sporring
2006 ed.
MICCAI (2)
Rasmus Larsen, Mads Nielsen, Jon Sporring
2006 conf
MICCAI (1)
Marleen de Bruijne, Michael T. Lund, László B. Tankó, Paola Pettersen, Mads Nielsen
2006 J jnl
J. Math. Imaging Vis.
Ole Fogh Olsen, Mads Nielsen
2006 conf
Digital Mammography / IWDM
Jakob Raundahl, Marco Loog, Mads Nielsen
2005 conf
Scale-Space
Sune Høgild Keller, François Lauze, Mads Nielsen
2005 conf
VLSM
François Lauze, Mads Nielsen
2005 B conf
Image Processing
Jenny Folkesson, Erik Dam, Paola Pettersen, Ole Fogh Olsen, Mads Nielsen, Claus Christiansen
2005 conf
IPMI
Marleen de Bruijne, Mads Nielsen
2005 conf
Scale-Space
Kim Steenstrup Pedersen, Remco Duits, Mads Nielsen
2005 conf
CVBIA
Lars A. Conrad-Hansen, Marleen de Bruijne, François Lauze, László B. Tankó, Mads Nielsen
2005 B conf
Image Processing
Lars Arne Conrad-Hansen, François Lauze, László B. Tankó, Mads Nielsen
2005 B conf
Image Processing
Michael Tillge Lund, Marleen de Bruijne, László B. Tankó, Mads Nielsen
2004 conf
ECCV (4)
Mads Nielsen, Peter Johansen
2004 A conf
BMVC
François Lauze, Mads Nielsen
2004 B conf
Image Processing
Nanna Glerup, Mads Nielsen, Jon Sporring, Sven Kreiborg
2004 B conf
Image Processing
Jakob Raundahl, Mads Nielsen, Ole Fogh Olsen, Yu Zhao Bagger
2004 B conf
ETRA
Dan Witzner Hansen, David J. C. MacKay, John Paulin Hansen, Mads Nielsen
2004 conf
ECCV (2)
Arjan Kuijper, Ole Fogh Olsen, Peter J. Giblin, Philip Bille, Mads Nielsen
2004 conf
ICPR (3)
Marleen de Bruijne, Mads Nielsen
2004 B conf
Image Processing
Lars A. Conrad-Hansen, Jakob Raundahl, László B. Tankó, Mads Nielsen
2004 conf
MICCAI (1)
Marleen de Bruijne, Mads Nielsen
2003 conf
Scale-Space
Erik Dam, Ole Fogh Olsen, Mads Nielsen
2003 conf
Scale-Space
Jon Sporring, Niels Holm Olsen, Mads Nielsen
2003 J jnl
Int. J. Comput. Vis.
Martin Lillholm, Mads Nielsen, Lewis D. Griffin
2003 conf
Scale-Space
Marco Loog, Martin Lillholm, Mads Nielsen, Max A. Viergever
2003 conf
SCIA
Niels Holm Olsen, Jon Sporring, Mads Nielsen, Christina Hnida, Seren Ziebe
2002 conf
MICCAI (2)
Mads Nielsen, Peter Johansen, Andrew D. Jackson, Benny Lautrup
2002 ed.
ECCV (1)
Anders Heyden, Gunnar Sparr, Mads Nielsen, Peter Johansen
2002 ed.
ECCV (2)
Anders Heyden, Gunnar Sparr, Mads Nielsen, Peter Johansen
2002 ed.
ECCV (3)
Anders Heyden, Gunnar Sparr, Mads Nielsen, Peter Johansen
2002 ed.
ECCV (4)
Anders Heyden, Gunnar Sparr, Mads Nielsen, Peter Johansen
2002 A conf
WACV
Dan Witzner Hansen, John Paulin Hansen, Mads Nielsen, Anders Sewerin Johansen, Mikkel B. Stegmann
2002 J jnl
J. Math. Imaging Vis.
Mads Nielsen, Lars Kai Hansen, Peter Johansen, Jon Sporring
2002 Misc conf
MVA
Dan Witzner Hansen, Mads Nielsen, John Paulin Hansen, Anders Sewerin Johansen, Mikkel B. Stegmann
2001 conf
Scale-Space
Kim Steenstrup Pedersen, Mads Nielsen
2001 conf
Scale-Space
Erik Dam, Mads Nielsen
2001 conf
IWVF
Mads Nielsen, Ole Fogh Olsen, Michael Sig, Mikkel Sigurd
2001 J jnl
Medical Image Anal.
Per Rønsholt Andresen, Mads Nielsen
2001 conf
Scale-Space
Bart M. ter Haar Romeny, Luc Florack, Mads Nielsen
2001 conf
Scale-Space
Mads Nielsen, Martin Lillholm
2000 J jnl
J. Math. Imaging Vis.
Peter Johansen, Mads Nielsen, Ole Fogh Olsen
2000 conf
AFPAC
Niels Holm Olsen, Mads Nielsen
2000 A conf
MICCAI
Erik Dam, Mads Nielsen
2000 J jnl
Image Vis. Comput.
Jon Sporring, Ole Fogh Olsen, Mads Nielsen, Joachim Weickert
2000 J jnl
J. Vis. Commun. Image Represent.
Olivier D. Faugeras, Mads Nielsen, Pietro Perona, Bart M. ter Haar Romeny, Guillermo Sapiro
2000 J jnl
J. Vis. Commun. Image Represent.
Kim Steenstrup Pedersen, Mads Nielsen
1999 J jnl
J. Math. Imaging Vis.
Mads Nielsen, Robert Maas, Wiro J. Niessen, Luc Florack, Bart M. ter Haar Romeny
1999 A conf
MICCAI
Per Rønsholt Andresen, Mads Nielsen
1999 ed.
Scale-Space
Mads Nielsen, Peter Johansen, Ole Fogh Olsen, Joachim Weickert
1999 conf
Scale-Space
Kim Steenstrup Pedersen, Mads Nielsen
1998 A conf
MICCAI
Per Rønsholt Andresen, Mads Nielsen, Sven Kreiborg
1998 B conf
ICPR
Jon Sporring, Mads Nielsen, Joachim Weickert, Ole Fogh Olsen
1998 conf
ICIP (3)
Mads Nielsen, Per Rønsholt Andresen
1998 J jnl
Int. J. Comput. Vis.
Luc Florack, Wiro J. Niessen, Mads Nielsen
1998 conf
ECCV (2)
Mads Nielsen, Ole Fogh Olsen
1997 book
Jon Sporring, Mads Nielsen, Luc Florack, Peter Johansen
1997 conf
Scale-Space
Ole Fogh Olsen, Mads Nielsen
1997 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Mads Nielsen
1997 J jnl
Comput. Vis. Image Underst.
Wiro J. Niessen, James S. Duncan, Mads Nielsen, Luc Florack, Bart M. ter Haar Romeny, Max A. Viergever
1997 conf
ICIAP (1)
Ole Fogh Olsen, Mads Nielsen
1997 conf
Scale-Space
Mads Nielsen, Wiro J. Niessen, Robert Maas, Luc Florack, Bart M. ter Haar Romeny
1997 J jnl
J. Math. Imaging Vis.
Mads Nielsen, Luc Florack, Rachid Deriche
1997 ch.
Gaussian Scale-Space Theory
Mads Nielsen
1996 conf
ECCV (2)
Mads Nielsen, Luc Florack, Rachid Deriche
1995 A* conf
ICCV
Mads Nielsen
1993 A conf
BMVC
Mads Nielsen
1993 A conf
BMVC
Mads Nielsen
tests/unit/test_apk_process_method.py
← Index tests/unit/test_apk_process_method.py python
"""Mock-based tests for APKCodeAnalyzer._process_method and androguard integration.

Tests the boundary between our code and androguard objects, covering:
- xref extraction (get_xref_from / get_xref_to) for both 4.x and 3.x APIs
- external method skipping
- library method filtering
- smali lookup and androguard fallback disassembly
- deduplication of content hashes
- full output population (all result dict keys)
- minimum instruction filtering
"""
from dataclasses import dataclass
from typing import List
from unittest.mock import MagicMock, Mock, patch, PropertyMock

import pytest

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


# ---------------------------------------------------------------------------
# Helpers: build mock androguard objects
# ---------------------------------------------------------------------------

SAMPLE_SMALI_BODY = """\
.locals 2
const/4 v0, 0x0
invoke-virtual {p0, v0}, Lcom/example/Foo;->bar(I)V
iget-object v1, p0, Lcom/example/Foo;->name:Ljava/lang/String;
add-int v0, v0, v1
return-void
"""

SAMPLE_JAVA_SOURCE = """\
public void doStuff() {
    int x = 0;
    bar(x);
    String n = this.name;
    x = x + n;
}
"""


def _make_encoded_method(
    class_name="Lcom/example/Foo;",
    method_name="doStuff",
    descriptor="()V",
    code=None,
):
    """Create a mock EncodedMethod."""
    enc = MagicMock()
    enc.get_class_name.return_value = class_name
    enc.get_name.return_value = method_name
    enc.get_descriptor.return_value = descriptor
    enc.get_code.return_value = code
    return enc


def _make_xref_entry_4x(class_name, method_name, offset=0):
    """Create a mock xref tuple in androguard 4.x format.

    4.x: (ClassAnalysis, MethodAnalysis, offset)
    MethodAnalysis has .get_method() returning the EncodedMethod.
    """
    ref_class = MagicMock()
    ref_method = MagicMock()
    inner_enc = MagicMock()
    inner_enc.get_class_name.return_value = class_name
    inner_enc.get_name.return_value = method_name
    ref_method.get_method.return_value = inner_enc
    # Remove direct get_class_name/get_name to simulate 4.x behavior
    del ref_method.get_class_name
    del ref_method.get_name
    return (ref_class, ref_method, offset)


def _make_xref_entry_3x(class_name, method_name, offset=0):
    """Create a mock xref tuple in androguard 3.x format.

    3.x: (ClassAnalysis, EncodedMethod, offset)
    EncodedMethod has .get_class_name() and .get_name() directly.
    """
    ref_class = MagicMock()
    ref_method = MagicMock(spec=[
        "get_class_name", "get_name",
    ])
    ref_method.get_class_name.return_value = class_name
    ref_method.get_name.return_value = method_name
    return (ref_class, ref_method, offset)


def _make_method_analysis(
    encoded=None,
    is_external=False,
    xref_from=None,
    xref_to=None,
):
    """Create a mock MethodAnalysis."""
    method = MagicMock()
    method.is_external.return_value = is_external
    method.get_method.return_value = encoded or _make_encoded_method()
    method.get_xref_from.return_value = xref_from or []
    method.get_xref_to.return_value = xref_to or []
    return method


def _make_analyzer(min_instructions=1):
    """Create an APKCodeAnalyzer with mocked dependencies."""
    with patch(
        "redb.extractors.decompiler.apk.analyzer.JADXDecompiler"
    ), patch(
        "redb.extractors.decompiler.apk.analyzer.ApktoolDisassembler"
    ):
        from redb.extractors.decompiler.apk.analyzer import APKCodeAnalyzer
        analyzer = APKCodeAnalyzer("/fake/path.apk")
        analyzer.min_instructions = min_instructions
        analyzer.library_filter = MagicMock()
        analyzer.library_filter.is_library.return_value = False
        return analyzer


def _empty_results():
    """Create a fresh empty results dict."""
    return {
        "decompiled_content": [],
        "decompiled_refs": [],
        "smali_content": [],
        "smali_refs": [],
        "similarity_metrics": [],
        "cfg": [],
        "analysis_errors": [],
    }


def _make_smali_method(body=SAMPLE_SMALI_BODY, instruction_count=5):
    """Create a mock SmaliMethod."""
    m = MagicMock()
    m.body = body
    m.instruction_count = instruction_count
    m.register_count = 2
    return m


# ---------------------------------------------------------------------------
# Tests: xref extraction
# ---------------------------------------------------------------------------

class TestXrefExtraction:
    """Tests that xrefs are correctly extracted from androguard objects."""

    def test_xref_from_androguard_4x(self):
        """4.x: ref_method.get_method().get_class_name() path."""
        analyzer = _make_analyzer()
        results = _empty_results()
        method_key = "Lcom/example/Foo;->doStuff()V"

        xref_from = [
            _make_xref_entry_4x("Lcom/example/Caller;", "init", 42),
            _make_xref_entry_4x("Lcom/example/Other;", "run", 100),
        ]
        method = _make_method_analysis(xref_from=xref_from)

        smali_methods = {method_key: _make_smali_method()}
        java_methods = {"com.example.Foo.doStuff": SAMPLE_JAVA_SOURCE}

        analyzer._process_method(
            method, smali_methods, java_methods,
            results, set(), set(),
        )

        assert len(results["decompiled_refs"]) == 1
        ref = results["decompiled_refs"][0]
        assert ref["functions_caller"] == [
            "Lcom/example/Caller;->init",
            "Lcom/example/Other;->run",
        ]

    def test_xref_to_androguard_4x(self):
        """4.x: callees extracted via get_method() unwrap."""
        analyzer = _make_analyzer()
        results = _empty_results()
        method_key = "Lcom/example/Foo;->doStuff()V"

        xref_to = [
            _make_xref_entry_4x("Lcom/example/Dep;", "calculate", 10),
        ]
        method = _make_method_analysis(xref_to=xref_to)

        smali_methods = {method_key: _make_smali_method()}
        java_methods = {"com.example.Foo.doStuff": SAMPLE_JAVA_SOURCE}

        analyzer._process_method(
            method, smali_methods, java_methods,
            results, set(), set(),
        )

        ref = results["decompiled_refs"][0]
        assert ref["functions_call"] == ["Lcom/example/Dep;->calculate"]

    def test_xref_from_androguard_3x_fallback(self):
        """3.x: ref_method.get_class_name() direct access fallback."""
        analyzer = _make_analyzer()
        results = _empty_results()
        method_key = "Lcom/example/Foo;->doStuff()V"

        xref_from = [
            _make_xref_entry_3x("Lcom/example/OldCaller;", "legacy"),
        ]
        method = _make_method_analysis(xref_from=xref_from)

        smali_methods = {method_key: _make_smali_method()}
        java_methods = {"com.example.Foo.doStuff": SAMPLE_JAVA_SOURCE}

        analyzer._process_method(
            method, smali_methods, java_methods,
            results, set(), set(),
        )

        ref = results["decompiled_refs"][0]
        assert ref["functions_caller"] == ["Lcom/example/OldCaller;->legacy"]

    def test_xref_to_androguard_3x_fallback(self):
        """3.x: callees via direct access fallback."""
        analyzer = _make_analyzer()
        results = _empty_results()
        method_key = "Lcom/example/Foo;->doStuff()V"

        xref_to = [
            _make_xref_entry_3x("Lcom/example/OldDep;", "compute"),
        ]
        method = _make_method_analysis(xref_to=xref_to)

        smali_methods = {method_key: _make_smali_method()}
        java_methods = {"com.example.Foo.doStuff": SAMPLE_JAVA_SOURCE}

        analyzer._process_method(
            method, smali_methods, java_methods,
            results, set(), set(),
        )

        ref = results["decompiled_refs"][0]
        assert ref["functions_call"] == ["Lcom/example/OldDep;->compute"]

    def test_empty_xrefs(self):
        """No xrefs produces empty lists, not None."""
        analyzer = _make_analyzer()
        results = _empty_results()
        method_key = "Lcom/example/Foo;->doStuff()V"

        method = _make_method_analysis()
        smali_methods = {method_key: _make_smali_method()}
        java_methods = {"com.example.Foo.doStuff": SAMPLE_JAVA_SOURCE}

        analyzer._process_method(
            method, smali_methods, java_methods,
            results, set(), set(),
        )

        ref = results["decompiled_refs"][0]
        assert ref["functions_caller"] == []
        assert ref["functions_call"] == []

    def test_xref_exception_does_not_crash(self):
        """If get_xref_from() itself throws, method still processes."""
        analyzer = _make_analyzer()
        results = _empty_results()
        method_key = "Lcom/example/Foo;->doStuff()V"

        method = _make_method_analysis()
        method.get_xref_from.side_effect = RuntimeError("xref table corrupt")
        method.get_xref_to.side_effect = RuntimeError("xref table corrupt")

        smali_methods = {method_key: _make_smali_method()}
        java_methods = {"com.example.Foo.doStuff": SAMPLE_JAVA_SOURCE}

        analyzer._process_method(
            method, smali_methods, java_methods,
            results, set(), set(),
        )

        # Method should still be processed with empty xrefs
        assert len(results["smali_refs"]) == 1
        ref = results["decompiled_refs"][0]
        assert ref["functions_caller"] == []
        assert ref["functions_call"] == []

    def test_multiple_xrefs(self):
        """Multiple callers and callees are all captured."""
        analyzer = _make_analyzer()
        results = _empty_results()
        method_key = "Lcom/example/Foo;->doStuff()V"

        xref_from = [
            _make_xref_entry_4x("Lcom/A;", "a1"),
            _make_xref_entry_4x("Lcom/B;", "b1"),
            _make_xref_entry_4x("Lcom/C;", "c1"),
        ]
        xref_to = [
            _make_xref_entry_4x("Lcom/D;", "d1"),
            _make_xref_entry_4x("Lcom/E;", "e1"),
        ]
        method = _make_method_analysis(xref_from=xref_from, xref_to=xref_to)

        smali_methods = {method_key: _make_smali_method()}
        java_methods = {"com.example.Foo.doStuff": SAMPLE_JAVA_SOURCE}

        analyzer._process_method(
            method, smali_methods, java_methods,
            results, set(), set(),
        )

        ref = results["decompiled_refs"][0]
        assert len(ref["functions_caller"]) == 3
        assert len(ref["functions_call"]) == 2


# ---------------------------------------------------------------------------
# Tests: method filtering and skipping
# ---------------------------------------------------------------------------

class TestMethodFiltering:
    """Tests for external/library/min-instruction filtering."""

    def test_external_method_skipped(self):
        """External methods (no code body) produce no output."""
        analyzer = _make_analyzer()
        results = _empty_results()

        method = _make_method_analysis(is_external=True)

        analyzer._process_method(
            method, {}, {}, results, set(), set(),
        )

        assert all(len(v) == 0 for v in results.values())

    def test_library_method_skipped(self):
        """Library methods produce no output."""
        analyzer = _make_analyzer()
        analyzer.library_filter.is_library.return_value = True
        results = _empty_results()

        method = _make_method_analysis()

        analyzer._process_method(
            method, {}, {}, results, set(), set(),
        )

        assert all(len(v) == 0 for v in results.values())

    def test_min_instruction_filter(self):
        """Methods below min_instructions threshold are skipped."""
        analyzer = _make_analyzer(min_instructions=10)
        results = _empty_results()
        method_key = "Lcom/example/Foo;->doStuff()V"

        method = _make_method_analysis()
        # Only 3 instructions — below threshold of 10
        smali_methods = {method_key: _make_smali_method(instruction_count=3)}

        analyzer._process_method(
            method, smali_methods, {}, results, set(), set(),
        )

        assert all(len(v) == 0 for v in results.values())

    def test_method_above_min_instructions_processed(self):
        """Methods at or above threshold are processed."""
        analyzer = _make_analyzer(min_instructions=5)
        results = _empty_results()
        method_key = "Lcom/example/Foo;->doStuff()V"

        method = _make_method_analysis()
        smali_methods = {method_key: _make_smali_method(instruction_count=5)}

        analyzer._process_method(
            method, smali_methods, {}, results, set(), set(),
        )

        assert len(results["smali_content"]) == 1
        assert len(results["smali_refs"]) == 1


# ---------------------------------------------------------------------------
# Tests: smali body lookup and androguard fallback
# ---------------------------------------------------------------------------

class TestSmaliLookup:
    """Tests for smali body lookup from apktool and androguard fallback."""

    def test_apktool_smali_used_when_available(self):
        """When apktool smali is available, it's used."""
        analyzer = _make_analyzer()
        results = _empty_results()
        method_key = "Lcom/example/Foo;->doStuff()V"

        method = _make_method_analysis()
        smali_methods = {method_key: _make_smali_method()}

        analyzer._process_method(
            method, smali_methods, {}, results, set(), set(),
        )

        assert len(results["smali_content"]) == 1
        assert results["smali_content"][0]["smali_method"] == SAMPLE_SMALI_BODY

    def test_androguard_fallback_when_no_apktool(self):
        """When apktool smali is missing, _disassemble_with_androguard is used."""
        analyzer = _make_analyzer()
        results = _empty_results()

        # Create encoded method with code
        instruction1 = MagicMock()
        instruction1.get_name.return_value = "const/4"
        instruction1.get_output.return_value = "v0, 0x0"
        instruction2 = MagicMock()
        instruction2.get_name.return_value = "invoke-virtual"
        instruction2.get_output.return_value = "v0, Lcom/Foo;->bar()V"
        instruction3 = MagicMock()
        instruction3.get_name.return_value = "add-int"
        instruction3.get_output.return_value = "v0, v1, v2"
        instruction4 = MagicMock()
        instruction4.get_name.return_value = "sub-int"
        instruction4.get_output.return_value = "v3, v0, v1"
        instruction5 = MagicMock()
        instruction5.get_name.return_value = "return-void"
        instruction5.get_output.return_value = ""

        code = MagicMock()
        code.get_registers_size.return_value = 4
        bytecode = MagicMock()
        bytecode.get_instructions.return_value = [
            instruction1, instruction2, instruction3, instruction4, instruction5,
        ]
        code.get_bc.return_value = bytecode

        encoded = _make_encoded_method(code=code)
        method = _make_method_analysis(encoded=encoded)

        # Empty smali_methods — forces androguard fallback
        analyzer._process_method(
            method, {}, {}, results, set(), set(),
        )

        assert len(results["smali_content"]) == 1
        body = results["smali_content"][0]["smali_method"]
        assert "const/4" in body
        assert "return-void" in body

    def test_androguard_fallback_no_code(self):
        """When encoded method has no code, method is skipped."""
        analyzer = _make_analyzer()
        results = _empty_results()

        encoded = _make_encoded_method(code=None)
        method = _make_method_analysis(encoded=encoded)

        analyzer._process_method(
            method, {}, {}, results, set(), set(),
        )

        assert all(len(v) == 0 for v in results.values())

    def test_androguard_fallback_bytecode_exception(self):
        """When bytecode iteration throws, method is skipped gracefully."""
        analyzer = _make_analyzer()
        results = _empty_results()

        code = MagicMock()
        code.get_registers_size.return_value = 2
        bytecode = MagicMock()
        bytecode.get_instructions.side_effect = RuntimeError("bad bytecode")
        code.get_bc.return_value = bytecode

        encoded = _make_encoded_method(code=code)
        method = _make_method_analysis(encoded=encoded)

        analyzer._process_method(
            method, {}, {}, results, set(), set(),
        )

        # Should not crash, but no content produced
        assert len(results["smali_content"]) == 0


# ---------------------------------------------------------------------------
# Tests: output population and deduplication
# ---------------------------------------------------------------------------

class TestOutputPopulation:
    """Tests that all result dict keys are correctly populated."""

    def _process_standard_method(self, with_java=True):
        """Helper: process a standard method and return results."""
        analyzer = _make_analyzer()
        results = _empty_results()
        method_key = "Lcom/example/Foo;->doStuff()V"

        xref_from = [_make_xref_entry_4x("Lcom/Caller;", "call")]
        xref_to = [_make_xref_entry_4x("Lcom/Dep;", "dep")]
        method = _make_method_analysis(
            xref_from=xref_from, xref_to=xref_to
        )

        smali_methods = {method_key: _make_smali_method()}
        java_methods = {}
        if with_java:
            java_methods = {"com.example.Foo.doStuff": SAMPLE_JAVA_SOURCE}

        analyzer._process_method(
            method, smali_methods, java_methods,
            results, set(), set(),
        )
        return results

    def test_smali_content_populated(self):
        results = self._process_standard_method()
        assert len(results["smali_content"]) == 1
        entry = results["smali_content"][0]
        assert "smali_method_hash" in entry
        assert entry["smali_method"] == SAMPLE_SMALI_BODY
        assert entry["smali_method_type"] == "USER"
        assert entry["smali_instructions_count"] == 5
        assert isinstance(entry["smali_has_string_encryption"], bool)
        assert isinstance(entry["smali_has_reflection_calls"], bool)
        assert isinstance(entry["smali_excessive_goto_count"], bool)

    def test_smali_refs_populated(self):
        results = self._process_standard_method()
        assert len(results["smali_refs"]) == 1
        ref = results["smali_refs"][0]
        assert "smali_method_hash" in ref
        assert ref["smali_class_name"] == "com.example.Foo"
        assert ref["smali_method_name"] == "doStuff"
        assert ref["smali_method_signature"] == "()V"

    def test_decompiled_content_populated_with_java(self):
        results = self._process_standard_method(with_java=True)
        assert len(results["decompiled_content"]) == 1
        entry = results["decompiled_content"][0]
        assert "decompiled_method_hash" in entry
        assert entry["decompiled_method"] == SAMPLE_JAVA_SOURCE

    def test_decompiled_refs_populated_with_java(self):
        results = self._process_standard_method(with_java=True)
        assert len(results["decompiled_refs"]) == 1
        ref = results["decompiled_refs"][0]
        assert "decompiled_method_hash" in ref
        assert "smali_method_hash" in ref
        assert ref["decompiled_class_name"] == "com.example.Foo"
        assert ref["decompiled_method_name"] == "doStuff"
        assert "decompiled_method_prototype" in ref
        assert ref["functions_caller"] == ["Lcom/Caller;->call"]
        assert ref["functions_call"] == ["Lcom/Dep;->dep"]

    def test_no_decompiled_without_java(self):
        results = self._process_standard_method(with_java=False)
        assert len(results["decompiled_content"]) == 0
        assert len(results["decompiled_refs"]) == 0
        # Smali should still be there
        assert len(results["smali_content"]) == 1

    def test_similarity_metrics_populated(self):
        results = self._process_standard_method()
        assert len(results["similarity_metrics"]) == 1
        sim = results["similarity_metrics"][0]
        assert "smali_method_hash" in sim
        assert "cyclomatic_complexity" in sim
        assert "minhash" in sim
        assert isinstance(sim["minhash"], list)
        # block_count moved to cfg table
        assert "block_count" not in sim

    def test_cfg_entry_populated(self):
        results = self._process_standard_method()
        assert len(results["cfg"]) == 1
        cfg = results["cfg"][0]
        assert "smali_method_hash" in cfg
        assert "block_count" in cfg
        assert "cfg_topology_hash" in cfg
        assert "prime_product_smali" in cfg
        assert "wl_minhash" in cfg
        assert "bb_features" in cfg
        assert isinstance(cfg["bb_features"], list)
        for feat in cfg["bb_features"]:
            assert len(feat) == 8

    def test_smali_deduplication(self):
        """Same smali body processed twice produces one content entry."""
        analyzer = _make_analyzer()
        results = _empty_results()
        method_key = "Lcom/example/Foo;->doStuff()V"
        seen_smali = set()

        method = _make_method_analysis()
        smali_methods = {method_key: _make_smali_method()}

        # Process same method twice
        analyzer._process_method(
            method, smali_methods, {}, results, set(), seen_smali,
        )
        analyzer._process_method(
            method, smali_methods, {}, results, set(), seen_smali,
        )

        # Content deduplicated, but refs are per-call
        assert len(results["smali_content"]) == 1
        assert len(results["smali_refs"]) == 2

    def test_decompiled_deduplication(self):
        """Same Java source processed twice produces one content entry."""
        analyzer = _make_analyzer()
        results = _empty_results()
        method_key = "Lcom/example/Foo;->doStuff()V"
        seen_decompiled = set()
        seen_smali = set()

        method = _make_method_analysis()
        smali_methods = {method_key: _make_smali_method()}
        java_methods = {"com.example.Foo.doStuff": SAMPLE_JAVA_SOURCE}

        analyzer._process_method(
            method, smali_methods, java_methods,
            results, seen_decompiled, seen_smali,
        )
        analyzer._process_method(
            method, smali_methods, java_methods,
            results, seen_decompiled, seen_smali,
        )

        assert len(results["decompiled_content"]) == 1
        assert len(results["decompiled_refs"]) == 2


# ---------------------------------------------------------------------------
# Tests: _disassemble_with_androguard
# ---------------------------------------------------------------------------

class TestDisassembleWithAndroguard:
    """Tests for the androguard bytecode disassembly fallback."""

    def test_no_code_returns_none(self):
        from redb.extractors.decompiler.apk.analyzer import APKCodeAnalyzer
        encoded = _make_encoded_method(code=None)
        body, count, regs = APKCodeAnalyzer._disassemble_with_androguard(encoded)
        assert body is None
        assert count == 0
        assert regs == 0

    def test_no_bytecode_returns_none(self):
        from redb.extractors.decompiler.apk.analyzer import APKCodeAnalyzer
        code = MagicMock()
        code.get_registers_size.return_value = 3
        code.get_bc.return_value = None
        encoded = _make_encoded_method(code=code)

        body, count, regs = APKCodeAnalyzer._disassemble_with_androguard(encoded)
        assert body is None
        assert count == 0
        assert regs == 3

    def test_basic_disassembly(self):
        from redb.extractors.decompiler.apk.analyzer import APKCodeAnalyzer

        instructions = []
        for name, output in [
            ("const/4", "v0, 0x0"),
            ("invoke-virtual", "v0, Lcom/Foo;->bar()V"),
            ("return-void", ""),
        ]:
            instr = MagicMock()
            instr.get_name.return_value = name
            instr.get_output.return_value = output
            instructions.append(instr)

        code = MagicMock()
        code.get_registers_size.return_value = 2
        bytecode = MagicMock()
        bytecode.get_instructions.return_value = instructions
        code.get_bc.return_value = bytecode

        encoded = _make_encoded_method(code=code)
        body, count, regs = APKCodeAnalyzer._disassemble_with_androguard(encoded)

        assert body is not None
        assert count == 3
        assert regs == 2
        assert "const/4" in body
        assert "return-void" in body

    def test_invoke_operands_normalized(self):
        """Androguard invoke output gets braces added around registers."""
        from redb.extractors.decompiler.apk.analyzer import APKCodeAnalyzer

        instr = MagicMock()
        instr.get_name.return_value = "invoke-virtual"
        # Androguard format: no braces
        instr.get_output.return_value = "v0, v1, Lcom/Foo;->bar(I)V"

        code = MagicMock()
        code.get_registers_size.return_value = 2
        bytecode = MagicMock()
        bytecode.get_instructions.return_value = [instr]
        code.get_bc.return_value = bytecode

        encoded = _make_encoded_method(code=code)
        body, count, regs = APKCodeAnalyzer._disassemble_with_androguard(encoded)

        # Should be normalized to apktool format with braces
        assert "{v0, v1}" in body

    def test_bytecode_exception_returns_none(self):
        from redb.extractors.decompiler.apk.analyzer import APKCodeAnalyzer

        code = MagicMock()
        code.get_registers_size.return_value = 2
        bytecode = MagicMock()
        bytecode.get_instructions.side_effect = RuntimeError("corrupt")
        code.get_bc.return_value = bytecode

        encoded = _make_encoded_method(code=code)
        body, count, regs = APKCodeAnalyzer._disassemble_with_androguard(encoded)

        assert body is None
        assert regs == 2