Ilias Diakonikolas

387 papers A* 154A 7Misc 1Journal 213Unranked 9
YearRankTypeTitle / Venue / Authors
2026 J jnl
CoRR
John Cooper, Ilias Diakonikolas, Mingchen Ma, Frederic Sala
2026 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Thanasis Pittas
2026 J jnl
CoRR
Ilias Diakonikolas, Giannis Iakovidis, Daniel M. Kane, Sihan Liu
2026 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane
2026 J jnl
CoRR
Ilias Diakonikolas, Giannis Iakovidis, Daniel M. Kane, Sihan Liu
2025 J jnl
CoRR
Ilias Diakonikolas, Nikos Zarifis
2025 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Mingchen Ma
2025 J jnl
CoRR
Alvan Arulandu, Ilias Diakonikolas, Daniel M. Kane, Jerry Zheng Li
2025 J jnl
CoRR
Ilias Diakonikolas, Giannis Iakovidis, Daniel M. Kane, Lisheng Ren
2025 A* conf
ICML
Ilias Diakonikolas, Daniel Kane, Sushrut Karmalkar, Sihan Liu, Thanasis Pittas
2025 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Sushrut Karmalkar, Sihan Liu, Thanasis Pittas
2025 A* conf
SODA
Ilias Diakonikolas, Daniel M. Kane, Jasper C. H. Lee, Thanasis Pittas
2025 J jnl
CoRR
Shuyao Li, Ilias Diakonikolas, Jelena Diakonikolas
2025 A* conf
ICML
Ilias Diakonikolas, Giannis Iakovidis, Daniel Kane, Thanasis Pittas
2025 J jnl
CoRR
Ilias Diakonikolas, Giannis Iakovidis, Daniel M. Kane, Thanasis Pittas
2025 A* conf
STOC
Ilias Diakonikolas, Daniel M. Kane, Sihan Liu, Thanasis Pittas
2025 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Sihan Liu, Thanasis Pittas
2025 A* conf
COLT
Ilias Diakonikolas, Daniel M. Kane, Lisheng Ren
2025 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Lisheng Ren
2025 A* conf
FOCS
Ilias Diakonikolas, Daniel M. Kane
2025 J jnl
CoRR
Ilias Diakonikolas, Chao Gao, Daniel M. Kane, John Lafferty, Ankit Pensia
2025 A* conf
COLT
Ilias Diakonikolas, Mingchen Ma, Lisheng Ren, Christos Tzamos
2025 J jnl
CoRR
Ilias Diakonikolas, Mingchen Ma, Lisheng Ren, Christos Tzamos
2025 J jnl
CoRR
Ilias Diakonikolas, Jelena Diakonikolas, Daniel M. Kane, Jasper C. H. Lee, Thanasis Pittas
2025 A* conf
ICML
Ilias Diakonikolas, Daniel Kane, Jasper C. H. Lee, Thanasis Pittas, David P. Woodruff, Samson Zhou
2025 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Jasper C. H. Lee, Thanasis Pittas, David P. Woodruff, Samson Zhou
2025 A* conf
ICML
Ilias Diakonikolas, Daniel Kane, Sushrut Karmalkar, Jasper C. H. Lee, Thanasis Pittas
2025 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Sushrut Karmalkar, Jasper C. H. Lee, Thanasis Pittas
2025 A* conf
ICML
Ilias Diakonikolas, Vasilis Kontonis, Christos Tzamos, Nikos Zarifis
2025 A* conf
FOCS
Ilias Diakonikolas, Daniel M. Kane, Sihan Liu, Thanasis Pittas
2025 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Sihan Liu, Thanasis Pittas
2025 J jnl
CoRR
Ilias Diakonikolas, Jingyi Gao, Daniel M. Kane, Sihan Liu, Christopher Ye
2025 A* conf
FOCS
Ilias Diakonikolas, Giannis Iakovidis, Daniel M. Kane, Nikos Zarifis
2025 J jnl
CoRR
Ilias Diakonikolas, Giannis Iakovidis, Daniel M. Kane, Nikos Zarifis
2025 A* conf
COLT
Nikos Zarifis, Puqian Wang, Ilias Diakonikolas, Jelena Diakonikolas
2025 J jnl
CoRR
Nikos Zarifis, Puqian Wang, Ilias Diakonikolas, Jelena Diakonikolas
2025 J jnl
CoRR
Puqian Wang, Nikos Zarifis, Ilias Diakonikolas, Jelena Diakonikolas
2025 A* conf
STOC
Ilias Diakonikolas, Samuel B. Hopkins, Ankit Pensia, Stefan Tiegel
2025 A* conf
STOC
Ilias Diakonikolas, Samuel B. Hopkins, Ankit Pensia, Stefan Tiegel
2025 A* conf
ICML
Ilias Diakonikolas, Mingchen Ma, Lisheng Ren, Christos Tzamos
2025 J jnl
CoRR
Ilias Diakonikolas, Mingchen Ma, Lisheng Ren, Christos Tzamos
2024 A* conf
NeurIPS
Ilias Diakonikolas, Nikos Zarifis
2024 A* conf
NeurIPS
Ilias Diakonikolas, Daniel M. Kane, Mingchen Ma
2024 A* conf
FOCS
Ilias Diakonikolas, Daniel M. Kane, Vasilis Kontonis, Christos Tzamos, Nikos Zarifis
2024 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Sihan Liu, Nikos Zarifis
2024 A* conf
COLT
Ilias Diakonikolas, Daniel M. Kane
2024 A* conf
ICML
Ilias Diakonikolas, Mingchen Ma, Lisheng Ren, Christos Tzamos
2024 J jnl
CoRR
Ilias Diakonikolas, Sushrut Karmalkar, Jongho Park, Christos Tzamos
2024 A* conf
ICLR
Xuefeng Du, Zhen Fang, Ilias Diakonikolas, Yixuan Li
2024 J jnl
CoRR
Xuefeng Du, Zhen Fang, Ilias Diakonikolas, Yixuan Li
2024 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane
2024 A* conf
NeurIPS
Shuyao Li, Sushrut Karmalkar, Ilias Diakonikolas, Jelena Diakonikolas
2024 J jnl
CoRR
Shuyao Li, Sushrut Karmalkar, Ilias Diakonikolas, Jelena Diakonikolas
2024 J jnl
CoRR
Ilias Diakonikolas, Vasilis Kontonis, Christos Tzamos, Nikos Zarifis
2024 A* conf
SODA
Daniel M. Kane, Ilias Diakonikolas, Hanshen Xiao, Sihan Liu
2024 A* conf
NeurIPS
Ilias Diakonikolas, Lisheng Ren, Nikos Zarifis
2024 J jnl
CoRR
Ilias Diakonikolas, Lisheng Ren, Nikos Zarifis
2024 J jnl
CoRR
Shuyao Li, Yu Cheng, Ilias Diakonikolas, Jelena Diakonikolas, Rong Ge, Stephen J. Wright
2024 A* conf
ICML
Ilias Diakonikolas, Daniel Kane, Sushrut Karmalkar, Ankit Pensia, Thanasis Pittas
2024 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Sushrut Karmalkar, Ankit Pensia, Thanasis Pittas
2024 A* conf
ICML
Nikos Zarifis, Puqian Wang, Ilias Diakonikolas, Jelena Diakonikolas
2024 J jnl
CoRR
Nikos Zarifis, Puqian Wang, Ilias Diakonikolas, Jelena Diakonikolas
2024 J jnl
CoRR
Ilias Diakonikolas, Daniel Kane, Lisheng Ren, Yuxin Sun
2024 A* conf
NeurIPS
Puqian Wang, Nikos Zarifis, Ilias Diakonikolas, Jelena Diakonikolas
2024 J jnl
CoRR
Puqian Wang, Nikos Zarifis, Ilias Diakonikolas, Jelena Diakonikolas
2024 J jnl
CoRR
Ilias Diakonikolas, Samuel B. Hopkins, Ankit Pensia, Stefan Tiegel
2024 J jnl
CoRR
Ilias Diakonikolas, Samuel B. Hopkins, Ankit Pensia, Stefan Tiegel
2024 A* conf
COLT
Ilias Diakonikolas, Daniel M. Kane, Thanasis Pittas, Nikos Zarifis
2024 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Thanasis Pittas, Nikos Zarifis
2024 A* conf
FOCS
Ilias Diakonikolas, Sushrut Karmalkar, Shuo Pang, Aaron Potechin
2024 J jnl
CoRR
Ilias Diakonikolas, Sushrut Karmalkar, Shuo Pang, Aaron Potechin
2024 A* conf
STOC
Ilias Diakonikolas, Daniel M. Kane, Vasilis Kontonis, Sihan Liu, Nikos Zarifis
2024 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Vasilis Kontonis, Sihan Liu, Nikos Zarifis
2024 A* conf
COLT
Ilias Diakonikolas, Daniel M. Kane, Sihan Liu, Nikos Zarifis
2024 A* conf
STOC
Ilias Diakonikolas, Daniel M. Kane, Sihan Liu
2023 A* conf
COLT
Daniel Kane, Ilias Diakonikolas
2023 A* conf
NeurIPS
Ilias Diakonikolas, Daniel Kane, Jasper C. H. Lee, Ankit Pensia, Thanasis Pittas
2023 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Jasper C. H. Lee, Ankit Pensia, Thanasis Pittas
2023 A* conf
STOC
Ilias Diakonikolas, Christos Tzamos, Daniel M. Kane
2023 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Vasilis Kontonis, Christos Tzamos, Nikos Zarifis
2023 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Jasper C. H. Lee, Thanasis Pittas
2023 A* conf
COLT
Ilias Diakonikolas, Sushrut Karmalkar, Jongho Park, Christos Tzamos
2023 J jnl
CoRR
Ilias Diakonikolas, Sushrut Karmalkar, Jongho Park, Christos Tzamos
2023 A* conf
NeurIPS
Ilias Diakonikolas, Daniel Kane, Vasilis Kontonis, Sihan Liu, Nikos Zarifis
2023 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Vasilis Kontonis, Sihan Liu, Nikos Zarifis
2023 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane
2023 A* conf
NeurIPS
Ilias Diakonikolas, Sushrut Karmalkar, Jongho Park, Christos Tzamos
2023 conf
SOSA
Ilias Diakonikolas, Daniel M. Kane, Ankit Pensia
2023 A* conf
COLT
Ilias Diakonikolas, Jelena Diakonikolas, Daniel M. Kane, Puqian Wang, Nikos Zarifis
2023 J jnl
CoRR
Ilias Diakonikolas, Jelena Diakonikolas, Daniel M. Kane, Puqian Wang, Nikos Zarifis
2023 A* conf
NeurIPS
Ilias Diakonikolas, Daniel Kane, Ankit Pensia, Thanasis Pittas
2023 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Ankit Pensia, Thanasis Pittas
2023 A* conf
NeurIPS
Ilias Diakonikolas, Jelena Diakonikolas, Daniel Kane, Puqian Wang, Nikos Zarifis
2023 J jnl
CoRR
Ilias Diakonikolas, Jelena Diakonikolas, Daniel M. Kane, Puqian Wang, Nikos Zarifis
2023 A* conf
ICML
Ilias Diakonikolas, Daniel Kane, Lisheng Ren
2023 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Lisheng Ren
2023 A* conf
ICML
Ilias Diakonikolas, Daniel Kane, Ankit Pensia, Thanasis Pittas
2023 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Ankit Pensia, Thanasis Pittas
2023 J jnl
CoRR
Daniel M. Kane, Ilias Diakonikolas, Hanshen Xiao, Sihan Liu
2023 A* conf
NeurIPS
Shuyao Li, Yu Cheng, Ilias Diakonikolas, Jelena Diakonikolas, Rong Ge, Stephen J. Wright
2023 A* conf
ICML
Puqian Wang, Nikos Zarifis, Ilias Diakonikolas, Jelena Diakonikolas
2023 J jnl
CoRR
Puqian Wang, Nikos Zarifis, Ilias Diakonikolas, Jelena Diakonikolas
2023 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Thanasis Pittas, Nikos Zarifis
2023 A* conf
NeurIPS
Ilias Diakonikolas, Daniel Kane, Yuxin Sun
2023 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Yuxin Sun
2023 A* conf
COLT
Ilias Diakonikolas, Daniel M. Kane, Thanasis Pittas, Nikos Zarifis
2023 A* conf
NeurIPS
Ilias Diakonikolas, Daniel Kane, Lisheng Ren, Yuxin Sun
2023 A* conf
COLT
Ilias Diakonikolas, Vasilis Kontonis, Christos Tzamos, Nikos Zarifis
2023 J jnl
CoRR
Ilias Diakonikolas, Vasilis Kontonis, Christos Tzamos, Nikos Zarifis
2023 A* conf
COLT
Ilias Diakonikolas, Daniel M. Kane, Yuetian Luo, Anru Zhang
2023 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Sihan Liu
2022 J jnl
CoRR
Daniel M. Kane, Ilias Diakonikolas
2022 J jnl
CoRR
Ilias Diakonikolas, Christos Tzamos, Daniel M. Kane
2022 J jnl
Electron. Colloquium Comput. Complex.
Ilias Diakonikolas, Christos Tzamos, Daniel Kane
2022 A* conf
STOC
Ilias Diakonikolas, Daniel M. Kane, Daniel Kongsgaard, Jerry Li, Kevin Tian
2022 A* conf
NeurIPS
Ilias Diakonikolas, Daniel Kane, Pasin Manurangsi, Lisheng Ren
2022 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Pasin Manurangsi, Lisheng Ren
2022 A conf
AAMAS
Ilias Diakonikolas, Chrystalla Pavlou, John Peebles, Alistair Stewart
2022 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Ankit Pensia
2022 A conf
AISTATS
Ilias Diakonikolas, Daniel Kane, Pasin Manurangsi, Lisheng Ren
2022 A* conf
ICML
Ilias Diakonikolas, Vasilis Kontonis, Christos Tzamos, Nikos Zarifis
2022 A* conf
COLT
Ilias Diakonikolas, Vasilis Kontonis, Christos Tzamos, Nikos Zarifis
2022 J jnl
CoRR
Ilias Diakonikolas, Vasilis Kontonis, Christos Tzamos, Nikos Zarifis
2022 A* conf
STOC
Ilias Diakonikolas, Daniel M. Kane, Vasilis Kontonis, Christos Tzamos, Nikos Zarifis
2022 A* conf
NeurIPS
Ilias Diakonikolas, Daniel Kane, Sushrut Karmalkar, Ankit Pensia, Thanasis Pittas
2022 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Sushrut Karmalkar, Ankit Pensia, Thanasis Pittas
2022 J jnl
CoRR
Clément L. Canonne, Ilias Diakonikolas, Daniel M. Kane, Sihan Liu
2022 A* conf
COLT
Ilias Diakonikolas, Daniel Kane
2022 A* conf
NeurIPS
Clément L. Canonne, Ilias Diakonikolas, Daniel Kane, Sihan Liu
2022 A* conf
COLT
Ilias Diakonikolas, Daniel Kane
2022 J jnl
SIAM J. Comput.
Xi Chen, Ilias Diakonikolas, Anthi Orfanou, Dimitris Paparas, Xiaorui Sun, Mihalis Yannakakis
2022 A* conf
COLT
Ilias Diakonikolas, Daniel M. Kane, Yuxin Sun
2022 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Yuxin Sun
2022 A* conf
NeurIPS
Yu Cheng, Ilias Diakonikolas, Rong Ge, Shivam Gupta, Daniel Kane, Mahdi Soltanolkotabi
2022 A* conf
NeurIPS
Ilias Diakonikolas, Daniel Kane, Jasper C. H. Lee, Ankit Pensia
2022 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Jasper C. H. Lee, Ankit Pensia
2022 A* conf
COLT
Ilias Diakonikolas, Daniel M. Kane, Sushrut Karmalkar, Ankit Pensia, Thanasis Pittas
2022 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Sushrut Karmalkar, Ankit Pensia, Thanasis Pittas
2022 A* conf
STOC
Ainesh Bakshi, Ilias Diakonikolas, He Jia, Daniel M. Kane, Pravesh K. Kothari, Santosh S. Vempala
2022 A* conf
NeurIPS
Ilias Diakonikolas, Daniel Kane, Lisheng Ren, Yuxin Sun
2022 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Lisheng Ren, Yuxin Sun
2022 A* conf
ICML
Ilias Diakonikolas, Daniel M. Kane, Ankit Pensia, Thanasis Pittas
2022 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Ankit Pensia, Thanasis Pittas
2021 A* conf
COLT
Ilias Diakonikolas, Daniel M. Kane, Vasilis Kontonis, Christos Tzamos, Nikos Zarifis
2021 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Vasilis Kontonis, Christos Tzamos, Nikos Zarifis
2021 A* conf
COLT
Ilias Diakonikolas, Russell Impagliazzo, Daniel M. Kane, Rex Lei, Jessica Sorrell, Christos Tzamos
2021 J jnl
CoRR
Ilias Diakonikolas, Russell Impagliazzo, Daniel Kane, Rex Lei, Jessica Sorrell, Christos Tzamos
2021 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Daniel Kongsgaard, Jerry Li, Kevin Tian
2021 A* conf
STOC
Ilias Diakonikolas, Daniel M. Kane, Vasilis Kontonis, Christos Tzamos, Nikos Zarifis
2021 A* conf
NeurIPS
Ilias Diakonikolas, Daniel Kane, Christos Tzamos
2021 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Christos Tzamos
2021 A* conf
ICML
Ilias Diakonikolas, Vasilis Kontonis, Christos Tzamos, Ali Vakilian, Nikos Zarifis
2021 A* conf
NeurIPS
Ilias Diakonikolas, Daniel Kane, Daniel Kongsgaard, Jerry Li, Kevin Tian
2021 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane
2021 A* conf
STOC
Ilias Diakonikolas, Themis Gouleakis, Daniel M. Kane, John Peebles, Eric Price
2021 A* conf
COLT
Ilias Diakonikolas, Daniel M. Kane, Alistair Stewart, Yuxin Sun
2021 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Alistair Stewart, Yuxin Sun
2021 J jnl
CoRR
Yu Cheng, Ilias Diakonikolas, Daniel M. Kane, Rong Ge, Shivam Gupta, Mahdi Soltanolkotabi
2021 A* conf
ICDE
Stephen Macke, Maryam Aliakbarpour, Ilias Diakonikolas, Aditya G. Parameswaran, Ronitt Rubinfeld
2021 A* conf
NeurIPS
Ilias Diakonikolas, Jongho Park, Christos Tzamos
2021 J jnl
CoRR
Ilias Diakonikolas, Jongho Park, Christos Tzamos
2021 J jnl
Commun. ACM
Ilias Diakonikolas, Gautam Kamath, Daniel M. Kane, Jerry Li, Ankur Moitra, Alistair Stewart
2021 A* conf
NeurIPS
Ilias Diakonikolas, Daniel Kane, Ankit Pensia, Thanasis Pittas, Alistair Stewart
2021 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Ankit Pensia, Thanasis Pittas, Alistair Stewart
2021 A* conf
COLT
Ilias Diakonikolas, Daniel M. Kane, Thanasis Pittas, Nikos Zarifis
2021 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Thanasis Pittas, Nikos Zarifis
2021 A* conf
COLT
Ilias Diakonikolas, Daniel M. Kane
2021 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Vasilis Kontonis, Christos Tzamos, Nikos Zarifis
2020 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Vasilis Kontonis, Christos Tzamos, Nikos Zarifis
2020 A* conf
COLT
Ilias Diakonikolas, Daniel M. Kane, Vasilis Kontonis, Nikos Zarifis
2020 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Vasilis Kontonis, Nikos Zarifis
2020 A* conf
COLT
Ilias Diakonikolas, Surbhi Goel, Sushrut Karmalkar, Adam R. Klivans, Mahdi Soltanolkotabi
2020 J jnl
CoRR
Ilias Diakonikolas, Surbhi Goel, Sushrut Karmalkar, Adam R. Klivans, Mahdi Soltanolkotabi
2020 J jnl
CoRR
Ilias Diakonikolas, Jerry Li, Anastasia Voloshinov
2020 A* conf
ICML
Omar Montasser, Surbhi Goel, Ilias Diakonikolas, Nathan Srebro
2020 J jnl
CoRR
Omar Montasser, Surbhi Goel, Ilias Diakonikolas, Nathan Srebro
2020 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane
2020 J jnl
CoRR
Yu Cheng, Ilias Diakonikolas, Rong Ge, Mahdi Soltanolkotabi
2020 A* conf
ICML
Yu Cheng, Ilias Diakonikolas, Rong Ge, Mahdi Soltanolkotabi
2020 A* conf
COLT
Ilias Diakonikolas, Vasilis Kontonis, Christos Tzamos, Nikos Zarifis
2020 J jnl
CoRR
Ilias Diakonikolas, Vasilis Kontonis, Christos Tzamos, Nikos Zarifis
2020 J jnl
CoRR
Ilias Diakonikolas, Vasilis Kontonis, Christos Tzamos, Nikos Zarifis
2020 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Daniel Kongsgaard, Jerry Li, Kevin Tian
2020 A* conf
NeurIPS
Ilias Diakonikolas, Daniel Kane, Daniel Kongsgaard
2020 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Daniel Kongsgaard
2020 J jnl
Oper. Res.
David S. Johnson, Lee Breslau, Ilias Diakonikolas, Nick Duffield, Yu Gu, MohammadTaghi Hajiaghayi, Howard J. Karloff, Mauricio G. C. Resende, Subhabrata Sen
2020 A* conf
NeurIPS
Ilias Diakonikolas, Daniel Kane, Nikos Zarifis
2020 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Nikos Zarifis
2020 A* conf
NeurIPS
Ilias Diakonikolas, Vasilis Kontonis, Christos Tzamos, Nikos Zarifis
2020 J jnl
CoRR
Ilias Diakonikolas, Vasilis Kontonis, Christos Tzamos, Nikos Zarifis
2020 J jnl
CoRR
Ilias Diakonikolas, Themis Gouleakis, Daniel M. Kane, John Peebles, Eric Price
2020 J jnl
Electron. Colloquium Comput. Complex.
Ilias Diakonikolas, Themis Gouleakis, Daniel Kane, John Peebles, Eric Price
2020 A* conf
NeurIPS
Ilias Diakonikolas, Daniel M. Kane, Ankit Pensia
2020 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Ankit Pensia
2020 A* conf
FOCS
Ainesh Bakshi, Ilias Diakonikolas, Samuel B. Hopkins, Daniel Kane, Sushrut Karmalkar, Pravesh K. Kothari
2020 J jnl
CoRR
Stephen Macke, Maryam Aliakbarpour, Ilias Diakonikolas, Aditya G. Parameswaran, Ronitt Rubinfeld
2020 ch.
Beyond the Worst-Case Analysis of Algorithms
Ilias Diakonikolas, Daniel M. Kane
2020 J jnl
CoRR
Ainesh Bakshi, Ilias Diakonikolas, He Jia, Daniel M. Kane, Pravesh K. Kothari, Santosh S. Vempala
2020 J jnl
CoRR
Ilias Diakonikolas, Samuel B. Hopkins, Daniel Kane, Sushrut Karmalkar
2020 A* conf
FOCS
Ilias Diakonikolas, Daniel M. Kane
2020 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane
2020 J jnl
IEEE Trans. Inf. Theory
Clément L. Canonne, Ilias Diakonikolas, Daniel M. Kane, Alistair Stewart
2020 A* conf
NeurIPS
Ilias Diakonikolas, Daniel M. Kane, Pasin Manurangsi
2020 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Pasin Manurangsi
2020 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane
2019 A* conf
NeurIPS
Brian Axelrod, Ilias Diakonikolas, Alistair Stewart, Anastasios Sidiropoulos, Gregory Valiant
2019 J jnl
CoRR
Brian Axelrod, Ilias Diakonikolas, Anastasios Sidiropoulos, Alistair Stewart, Gregory Valiant
2019 J jnl
Chic. J. Theor. Comput. Sci.
Ilias Diakonikolas, Themis Gouleakis, John Peebles, Eric Price
2019 A* conf
COLT
Ilias Diakonikolas, Themis Gouleakis, Daniel M. Kane, Sankeerth Rao
2019 J jnl
CoRR
Ilias Diakonikolas, Themis Gouleakis, Daniel M. Kane, Sankeerth Rao
2019 A* conf
STOC
Ilias Diakonikolas, Daniel M. Kane
2019 A* conf
NeurIPS
Ilias Diakonikolas, Themis Gouleakis, Christos Tzamos
2019 J jnl
CoRR
Ilias Diakonikolas, Themis Gouleakis, Christos Tzamos
2019 A* conf
SODA
Ilias Diakonikolas, Weihao Kong, Alistair Stewart
2019 A* conf
NeurIPS
Kai Zheng, Haipeng Luo, Ilias Diakonikolas, Liwei Wang
2019 J jnl
CoRR
Kai Zheng, Haipeng Luo, Ilias Diakonikolas, Liwei Wang
2019 A* conf
COLT
Yu Cheng, Ilias Diakonikolas, Rong Ge, David P. Woodruff
2019 J jnl
CoRR
Yu Cheng, Ilias Diakonikolas, Rong Ge, David P. Woodruff
2019 A* conf
SODA
Yu Cheng, Ilias Diakonikolas, Rong Ge
2019 A* conf
NeurIPS
Ilias Diakonikolas, Daniel Kane, Pasin Manurangsi
2019 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Pasin Manurangsi
2019 A* conf
AAAI
Ilias Diakonikolas, Chrystalla Pavlou
2019 A* conf
NeurIPS
Ilias Diakonikolas, Daniel Kane, Sushrut Karmalkar, Eric Price, Alistair Stewart
2019 J jnl
CoRR
Ilias Diakonikolas, Sushrut Karmalkar, Daniel Kane, Eric Price, Alistair Stewart
2019 A* conf
NeurIPS
Maryam Aliakbarpour, Ilias Diakonikolas, Daniel Kane, Ronitt Rubinfeld
2019 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane
2019 J jnl
SIAM J. Comput.
Ilias Diakonikolas, Gautam Kamath, Daniel Kane, Jerry Li, Ankur Moitra, Alistair Stewart
2019 A* conf
ICML
Ilias Diakonikolas, Gautam Kamath, Daniel Kane, Jerry Li, Jacob Steinhardt, Alistair Stewart
2019 A* conf
COLT
Ilias Diakonikolas, Daniel M. Kane, John Peebles
2018 J jnl
CoRR
Ilias Diakonikolas, Anastasios Sidiropoulos, Alistair Stewart
2018 J jnl
Electron. Colloquium Comput. Complex.
Ilias Diakonikolas, Daniel Kane
2018 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane
2018 A* conf
ICML
Maryam Aliakbarpour, Ilias Diakonikolas, Ronitt Rubinfeld
2018 J jnl
CoRR
Ilias Diakonikolas, Weihao Kong, Alistair Stewart
2018 A* conf
COLT
Ilias Diakonikolas, Jerry Li, Ludwig Schmidt
2018 J jnl
CoRR
Ilias Diakonikolas, Jerry Li, Ludwig Schmidt
2018 J jnl
CoRR
Yu Cheng, Ilias Diakonikolas, Rong Ge
2018 A* conf
STOC
Ilias Diakonikolas, Daniel M. Kane, Alistair Stewart
2018 A* conf
STOC
Ilias Diakonikolas, Daniel M. Kane, Alistair Stewart
2018 A* conf
COLT
Timothy Carpenter, Ilias Diakonikolas, Anastasios Sidiropoulos, Alistair Stewart
2018 J jnl
CoRR
Timothy Carpenter, Ilias Diakonikolas, Anastasios Sidiropoulos, Alistair Stewart
2018 J jnl
CoRR
Ilias Diakonikolas, Chrystalla Pavlou
2018 A* ed.
STOC
Ilias Diakonikolas, David Kempe, Monika Henzinger
2018 A* conf
NeurIPS
Yu Cheng, Ilias Diakonikolas, Daniel Kane, Alistair Stewart
2018 A* conf
SODA
Ilias Diakonikolas, Gautam Kamath, Daniel M. Kane, Jerry Li, Ankur Moitra, Alistair Stewart
2018 A* conf
ICALP
Ilias Diakonikolas, Themis Gouleakis, John Peebles, Eric Price
2018 J jnl
CoRR
Ilias Diakonikolas, Gautam Kamath, Daniel M. Kane, Jerry Li, Jacob Steinhardt, Alistair Stewart
2018 A* conf
NeurIPS
Ilias Diakonikolas, Daniel M. Kane, Alistair Stewart
2018 Misc conf
ITA
Clément L. Canonne, Ilias Diakonikolas, Daniel M. Kane, Alistair Stewart
2018 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, John Peebles
2018 J jnl
Theory Comput. Syst.
Clément L. Canonne, Ilias Diakonikolas, Themis Gouleakis, Ronitt Rubinfeld
2018 A* conf
STOC
Clément L. Canonne, Ilias Diakonikolas, Daniel M. Kane, Alistair Stewart
2018 A* conf
NeurIPS
Alistair Stewart, Ilias Diakonikolas, Clément L. Canonne
2018 J jnl
Games Econ. Behav.
Xi Chen, Ilias Diakonikolas, Dimitris Paparas, Xiaorui Sun, Mihalis Yannakakis
2017 A* conf
ICML
Ilias Diakonikolas, Gautam Kamath, Daniel M. Kane, Jerry Li, Ankur Moitra, Alistair Stewart
2017 J jnl
CoRR
Ilias Diakonikolas, Gautam Kamath, Daniel M. Kane, Jerry Li, Ankur Moitra, Alistair Stewart
2017 conf
NIPS
Ilias Diakonikolas, Elena Grigorescu, Jerry Li, Abhiram Natarajan, Krzysztof Onak, Ludwig Schmidt
2017 J jnl
CoRR
Maryam Aliakbarpour, Ilias Diakonikolas, Ronitt Rubinfeld
2017 J jnl
CoRR
Clément L. Canonne, Ilias Diakonikolas, Alistair Stewart
2017 J jnl
Electron. Colloquium Comput. Complex.
Clément L. Canonne, Ilias Diakonikolas, Alistair Stewart
2017 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Alistair Stewart
2017 A* conf
COLT
Ilias Diakonikolas, Daniel M. Kane, Alistair Stewart
2017 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Alistair Stewart
2017 A* conf
ICALP
Ilias Diakonikolas, Daniel M. Kane, Vladimir Nikishkin
2017 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Vladimir Nikishkin
2017 A* conf
SODA
Yu Cheng, Ilias Diakonikolas, Alistair Stewart
2017 J jnl
CoRR
Ilias Diakonikolas, Gautam Kamath, Daniel M. Kane, Jerry Li, Ankur Moitra, Alistair Stewart
2017 A* conf
SODA
Jayadev Acharya, Ilias Diakonikolas, Jerry Li, Ludwig Schmidt
2017 J jnl
CoRR
Ilias Diakonikolas, Themis Gouleakis, John Peebles, Eric Price
2017 J jnl
Electron. Colloquium Comput. Complex.
Ilias Diakonikolas, Themis Gouleakis, John Peebles, Eric Price
2017 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Alistair Stewart
2017 J jnl
Electron. Colloquium Comput. Complex.
Ilias Diakonikolas, Daniel M. Kane, Alistair Stewart
2017 A* conf
FOCS
Ilias Diakonikolas, Daniel M. Kane, Alistair Stewart
2017 A* conf
COLT
Clément L. Canonne, Ilias Diakonikolas, Daniel M. Kane, Alistair Stewart
2017 J jnl
CoRR
Clément L. Canonne, Ilias Diakonikolas, Daniel M. Kane, Alistair Stewart
2017 J jnl
Games Econ. Behav.
Anindya De, Ilias Diakonikolas, Rocco A. Servedio
2016 A* conf
FOCS
Ilias Diakonikolas, Daniel M. Kane
2016 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane
2016 J jnl
Electron. Colloquium Comput. Complex.
Ilias Diakonikolas, Daniel M. Kane
2016 J jnl
SIAM J. Discret. Math.
Anindya De, Ilias Diakonikolas, Rocco A. Servedio
2016 J jnl
CoRR
Ilias Diakonikolas, Themis Gouleakis, John Peebles, Eric Price
2016 J jnl
Electron. Colloquium Comput. Complex.
Ilias Diakonikolas, Themis Gouleakis, John Peebles, Eric Price
2016 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Alistair Stewart
2016 A* conf
ICML
Jayadev Acharya, Ilias Diakonikolas, Jerry Li, Ludwig Schmidt
2016 J jnl
CoRR
Jayadev Acharya, Ilias Diakonikolas, Jerry Li, Ludwig Schmidt
2016 J jnl
SIAM J. Comput.
Constantinos Daskalakis, Ilias Diakonikolas, Mihalis Yannakakis
2016 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Alistair Stewart
2016 ch.
Handbook of Big Data
Ilias Diakonikolas
2016 J jnl
CoRR
David S. Johnson, Lee Breslau, Ilias Diakonikolas, Nick G. Duffield, Yu Gu, MohammadTaghi Hajiaghayi, Howard J. Karloff, Mauricio G. C. Resende, Subhabrata Sen
2016 A* conf
COLT
Ilias Diakonikolas, Daniel M. Kane, Alistair Stewart
2016 J jnl
CoRR
Yu Cheng, Ilias Diakonikolas, Alistair Stewart
2016 A* conf
COLT
Ilias Diakonikolas, Daniel M. Kane, Alistair Stewart
2016 A* conf
FOCS
Ilias Diakonikolas, Gautam Kamath, Daniel M. Kane, Jerry Li, Ankur Moitra, Alistair Stewart
2016 J jnl
CoRR
Ilias Diakonikolas, Gautam Kamath, Daniel M. Kane, Jerry Zheng Li, Ankur Moitra, Alistair Stewart
2016 J jnl
CoRR
Yu Cheng, Ilias Diakonikolas, Daniel M. Kane, Alistair Stewart
2016 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Alistair Stewart
2016 J jnl
Electron. Colloquium Comput. Complex.
Ilias Diakonikolas, Daniel M. Kane, Alistair Stewart
2016 J jnl
CoRR
Clément L. Canonne, Ilias Diakonikolas, Daniel M. Kane, Alistair Stewart
2016 A conf
STACS
Clément L. Canonne, Ilias Diakonikolas, Themis Gouleakis, Ronitt Rubinfeld
2016 A* conf
STOC
Ilias Diakonikolas, Daniel M. Kane, Alistair Stewart
2015 conf
NIPS
Ilias Diakonikolas, Moritz Hardt, Ludwig Schmidt
2015 A* conf
PODS
Jayadev Acharya, Ilias Diakonikolas, Chinmay Hegde, Jerry Zheng Li, Ludwig Schmidt
2015 J jnl
Algorithmica
Constantinos Daskalakis, Ilias Diakonikolas, Rocco A. Servedio
2015 A* conf
SODA
Anindya De, Ilias Diakonikolas, Rocco A. Servedio
2015 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Alistair Stewart
2015 J jnl
Chic. J. Theor. Comput. Sci.
Ilias Diakonikolas, Ragesh Jaiswal, Rocco A. Servedio, Li-Yang Tan, Andrew Wan
2015 A* conf
FOCS
Xi Chen, Ilias Diakonikolas, Anthi Orfanou, Dimitris Paparas, Xiaorui Sun, Mihalis Yannakakis
2015 A* conf
FOCS
Ilias Diakonikolas, Daniel M. Kane, Vladimir Nikishkin
2015 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Vladimir Nikishkin
2015 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Alistair Stewart
2015 J jnl
CoRR
Jayadev Acharya, Ilias Diakonikolas, Jerry Zheng Li, Ludwig Schmidt
2015 A* conf
SODA
Ilias Diakonikolas, Daniel M. Kane, Vladimir Nikishkin
2015 J jnl
CoRR
Clément L. Canonne, Ilias Diakonikolas, Themis Gouleakis, Ronitt Rubinfeld
2015 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Alistair Stewart
2014 A* conf
SODA
Constantinos Daskalakis, Anindya De, Ilias Diakonikolas, Ankur Moitra, Rocco A. Servedio
2014 J jnl
Theory Comput.
Ilias Diakonikolas, Rocco A. Servedio, Li-Yang Tan, Andrew Wan
2014 J jnl
SIAM J. Comput.
Ilias Diakonikolas, Prasad Raghavendra, Rocco A. Servedio, Li-Yang Tan
2014 A conf
CCC
Anindya De, Ilias Diakonikolas, Rocco A. Servedio
2014 A* conf
STOC
Siu On Chan, Ilias Diakonikolas, Rocco A. Servedio, Xiaorui Sun
2014 J jnl
Theory Comput.
Constantinos Daskalakis, Ilias Diakonikolas, Rocco A. Servedio
2014 conf
NIPS
Siu On Chan, Ilias Diakonikolas, Rocco A. Servedio, Xiaorui Sun
2014 J jnl
CoRR
Siu On Chan, Ilias Diakonikolas, Rocco A. Servedio, Xiaorui Sun
2014 J jnl
J. ACM
Anindya De, Ilias Diakonikolas, Vitaly Feldman, Rocco A. Servedio
2014 A* conf
SODA
Siu On Chan, Ilias Diakonikolas, Paul Valiant, Gregory Valiant
2014 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Vladimir Nikishkin
2014 A* conf
SODA
Xi Chen, Ilias Diakonikolas, Dimitris Paparas, Xiaorui Sun, Mihalis Yannakakis
2013 J jnl
CoRR
Constantinos Daskalakis, Anindya De, Ilias Diakonikolas, Ankur Moitra, Rocco A. Servedio
2013 conf
ICALP (1)
Anindya De, Ilias Diakonikolas, Rocco A. Servedio
2013 J jnl
CoRR
Anindya De, Ilias Diakonikolas, Rocco A. Servedio
2013 J jnl
Electron. Colloquium Comput. Complex.
Anindya De, Ilias Diakonikolas, Rocco A. Servedio
2013 J jnl
CoRR
Anindya De, Ilias Diakonikolas, Rocco A. Servedio
2013 J jnl
Electron. Colloquium Comput. Complex.
Anindya De, Ilias Diakonikolas, Rocco A. Servedio
2013 J jnl
CoRR
Siu On Chan, Ilias Diakonikolas, Rocco A. Servedio, Xiaorui Sun
2013 J jnl
CoRR
Constantinos Daskalakis, Ilias Diakonikolas, Mihalis Yannakakis
2013 J jnl
Comput. Complex.
Ilias Diakonikolas, Rocco A. Servedio
2013 A* conf
FOCS
Constantinos Daskalakis, Ilias Diakonikolas, Ryan O'Donnell, Rocco A. Servedio, Li-Yang Tan
2013 A* conf
SODA
Siu On Chan, Ilias Diakonikolas, Rocco A. Servedio, Xiaorui Sun
2013 J jnl
CoRR
Siu On Chan, Ilias Diakonikolas, Gregory Valiant, Paul Valiant
2013 A* conf
SODA
Constantinos Daskalakis, Ilias Diakonikolas, Rocco A. Servedio, Gregory Valiant, Paul Valiant
2013 J jnl
CoRR
Xi Chen, Ilias Diakonikolas, Dimitris Paparas, Xiaorui Sun, Mihalis Yannakakis
2012 J jnl
CoRR
Anindya De, Ilias Diakonikolas, Rocco A. Servedio
2012 conf
ICALP (2)
Ilias Diakonikolas, Christos H. Papadimitriou, George Pierrakos, Yaron Singer
2012 J jnl
CoRR
Ilias Diakonikolas, Christos H. Papadimitriou, George Pierrakos, Yaron Singer
2012 J jnl
Electron. Colloquium Comput. Complex.
Anindya De, Ilias Diakonikolas, Rocco A. Servedio
2012 J jnl
CoRR
Anindya De, Ilias Diakonikolas, Rocco A. Servedio
2012 A* conf
SODA
Constantinos Daskalakis, Ilias Diakonikolas, Rocco A. Servedio
2012 J jnl
CoRR
Siu On Chan, Ilias Diakonikolas, Rocco A. Servedio, Xiaorui Sun
2012 A* conf
STOC
Constantinos Daskalakis, Ilias Diakonikolas, Rocco A. Servedio
2012 J jnl
CoRR
Anindya De, Ilias Diakonikolas, Vitaly Feldman, Rocco A. Servedio
2012 J jnl
Electron. Colloquium Comput. Complex.
Anindya De, Ilias Diakonikolas, Vitaly Feldman, Rocco A. Servedio
2012 A* conf
STOC
Anindya De, Ilias Diakonikolas, Vitaly Feldman, Rocco A. Servedio
2012 J jnl
CoRR
Ilias Diakonikolas, Ragesh Jaiswal, Rocco A. Servedio, Li-Yang Tan, Andrew Wan
2012 J jnl
CoRR
Anindya De, Ilias Diakonikolas, Rocco A. Servedio
2012 conf
ICALP (1)
Anindya De, Ilias Diakonikolas, Rocco A. Servedio
2012 J jnl
Electron. Colloquium Comput. Complex.
Anindya De, Ilias Diakonikolas, Rocco A. Servedio
2011
Ilias Diakonikolas
2011 A conf
ALENEX
Lee Breslau, Ilias Diakonikolas, Nick G. Duffield, Yu Gu, Mohammad Taghi Hajiaghayi, David S. Johnson, Howard J. Karloff, Mauricio G. C. Resende, Subhabrata Sen
2011 J jnl
Algorithmica
Ilias Diakonikolas, Homin K. Lee, Kevin Matulef, Rocco A. Servedio, Andrew Wan
2011 A* conf
SODA
Ilias Diakonikolas, Ryan O'Donnell, Rocco A. Servedio, Yi Wu
2011 J jnl
CoRR
Constantinos Daskalakis, Ilias Diakonikolas, Rocco A. Servedio
2011 J jnl
CoRR
Constantinos Daskalakis, Ilias Diakonikolas, Rocco A. Servedio
2011 J jnl
CoRR
Constantinos Daskalakis, Ilias Diakonikolas, Rocco A. Servedio
2011 A* conf
DAC
Hung-Yi Liu, Ilias Diakonikolas, Michele Petracca, Luca P. Carloni
2011 J jnl
CoRR
Constantinos Daskalakis, Ilias Diakonikolas, Rocco A. Servedio, Gregory Valiant, Paul Valiant
2010 A conf
CCC
Ilias Diakonikolas, Rocco A. Servedio, Li-Yang Tan, Andrew Wan
2010 A* conf
FOCS
Ilias Diakonikolas, Daniel M. Kane, Jelani Nelson
2010 J jnl
SIAM J. Comput.
Ilias Diakonikolas, Parikshit Gopalan, Ragesh Jaiswal, Rocco A. Servedio, Emanuele Viola
2010 A* conf
STOC
Ilias Diakonikolas, Prahladh Harsha, Adam R. Klivans, Raghu Meka, Prasad Raghavendra, Rocco A. Servedio, Li-Yang Tan
2010 J jnl
CoRR
Ilias Diakonikolas, Ryan O'Donnell, Rocco A. Servedio, Yi Wu
2010 A* conf
SODA
Constantinos Daskalakis, Ilias Diakonikolas, Mihalis Yannakakis
2009 J jnl
CoRR
Ilias Diakonikolas, Rocco A. Servedio, Li-Yang Tan, Andrew Wan
2009 J jnl
CoRR
Ilias Diakonikolas, Prasad Raghavendra, Rocco A. Servedio, Li-Yang Tan
2009 J jnl
CoRR
Ilias Diakonikolas, Daniel M. Kane, Jelani Nelson
2009 J jnl
Electron. Colloquium Comput. Complex.
Ilias Diakonikolas, Daniel M. Kane, Jelani Nelson
2009 J jnl
CoRR
Ilias Diakonikolas, Parikshit Gopalan, Ragesh Jaiswal, Rocco A. Servedio, Emanuele Viola
2009 A* conf
FOCS
Ilias Diakonikolas, Parikshit Gopalan, Ragesh Jaiswal, Rocco A. Servedio, Emanuele Viola
2009 J jnl
Electron. Colloquium Comput. Complex.
Ilias Diakonikolas, Parikshit Gopalan, Ragesh Jaiswal, Rocco A. Servedio, Emanuele Viola
2009 J jnl
CoRR
Ilias Diakonikolas, Rocco A. Servedio
2009 A conf
CCC
Ilias Diakonikolas, Rocco A. Servedio
2009 J jnl
SIAM J. Comput.
Ilias Diakonikolas, Mihalis Yannakakis
2008 J jnl
CoRR
Ilias Diakonikolas, Homin K. Lee, Kevin Matulef, Rocco A. Servedio, Andrew Wan
2008 conf
ICALP (1)
Ilias Diakonikolas, Homin K. Lee, Kevin Matulef, Rocco A. Servedio, Andrew Wan
2008 J jnl
CoRR
Ilias Diakonikolas, Mihalis Yannakakis
2008 A* conf
SODA
Ilias Diakonikolas, Mihalis Yannakakis
2007 conf
APPROX-RANDOM
Ilias Diakonikolas, Mihalis Yannakakis
2007 A* conf
FOCS
Ilias Diakonikolas, Homin K. Lee, Kevin Matulef, Krzysztof Onak, Ronitt Rubinfeld, Rocco A. Servedio, Andrew Wan
2007 J jnl
Electron. Colloquium Comput. Complex.
Ilias Diakonikolas, Homin K. Lee, Kevin Matulef, Krzysztof Onak, Ronitt Rubinfeld, Rocco A. Servedio, Andrew Wan
tests/unit/test_apk_extractors.py
← Index tests/unit/test_apk_extractors.py python
"""
Unit tests for APK extractors.

Tests tag(), get_clickhouse_table(), extract(), and prepare_export_data()
for all 8 APK extractors. Uses mocked androguard APK objects.
"""
import pytest
import os
import hashlib
import tempfile
import zipfile
from dataclasses import asdict
from unittest.mock import MagicMock, patch, PropertyMock

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


# ============================================================================
# Helpers
# ============================================================================

def _create_fake_apk(tmp_path, files=None):
    """Create a minimal valid ZIP file that pretends to be an APK.

    Args:
        tmp_path: Directory to write the fake APK into.
        files: Dict of {filename: content_bytes} to include in the ZIP.

    Returns:
        Path to the fake APK file.
    """
    apk_path = os.path.join(tmp_path, "test.apk")
    default_files = {
        "AndroidManifest.xml": b"<manifest/>",
        "classes.dex": b"dex\n035\x00" + b"\x00" * 100,
        "res/drawable/icon.png": b"\x89PNG" + b"\x00" * 50,
    }
    if files:
        default_files.update(files)

    with zipfile.ZipFile(apk_path, "w") as zf:
        for name, data in default_files.items():
            zf.writestr(name, data)
    return apk_path


def _make_mock_apk():
    """Create a mock androguard APK object with common return values."""
    mock_apk = MagicMock()
    mock_apk.get_package.return_value = "com.example.test"
    mock_apk.get_app_name.return_value = "Test App"
    mock_apk.get_androidversion_code.return_value = "10"
    mock_apk.get_androidversion_name.return_value = "1.2.3"
    mock_apk.get_min_sdk_version.return_value = "21"
    mock_apk.get_target_sdk_version.return_value = "33"
    mock_apk.get_effective_target_sdk_version.return_value = "33"
    mock_apk.get_main_activity.return_value = "com.example.test.MainActivity"
    mock_apk.get_attribute_value.return_value = None
    mock_apk.get_libraries.return_value = []
    mock_apk.get_files.return_value = [
        "AndroidManifest.xml", "classes.dex",
        "res/drawable/icon.png", "lib/armeabi-v7a/libnative.so",
        "assets/data.bin",
    ]
    mock_apk.get_permissions.return_value = [
        "android.permission.INTERNET",
        "android.permission.CAMERA",
    ]
    mock_apk.get_declared_permissions.return_value = {}
    mock_apk.get_activities.return_value = ["com.example.test.MainActivity"]
    mock_apk.get_services.return_value = ["com.example.test.MyService"]
    mock_apk.get_receivers.return_value = ["com.example.test.BootReceiver"]
    mock_apk.get_providers.return_value = []
    mock_apk.get_uses_implied_permission_list.return_value = []
    mock_apk.is_valid_APK.return_value = True
    mock_apk.get_certificates.return_value = []
    mock_apk.get_certificates_v1.return_value = []
    mock_apk.get_certificates_v2.return_value = []
    mock_apk.get_certificates_v3.return_value = []
    mock_apk.get_signature_names.return_value = []
    mock_apk.is_signed_v1.return_value = True
    mock_apk.is_signed_v2.return_value = True
    mock_apk.is_signed_v3.return_value = False
    return mock_apk


@pytest.fixture
def fake_apk_env(tmp_path):
    """Create a fake APK file and mock APK object."""
    apk_path = _create_fake_apk(str(tmp_path))
    mock_apk = _make_mock_apk()
    mock_logger = MagicMock()
    mock_exporters = [MagicMock()]
    return apk_path, mock_apk, mock_logger, mock_exporters


# ============================================================================
# APKFeaturesExtractor
# ============================================================================

class TestAPKFeaturesExtractor:

    def test_tag(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_features import APKFeaturesExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKFeaturesExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.tag() == "apk_features"

    def test_clickhouse_table(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_features import APKFeaturesExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKFeaturesExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.get_clickhouse_table() == "redb_apk_features"

    def test_extract_returns_dataclass(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_features import APKFeaturesExtractor
        from redb.models.dataclasses import APKFeatures

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKFeaturesExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()

        assert isinstance(result, APKFeatures)
        assert result.package_name == "com.example.test"
        assert result.app_name == "Test App"
        assert result.version_code == 10
        assert result.version_name == "1.2.3"
        assert result.min_sdk_version == 21
        assert result.target_sdk_version == 33
        assert result.main_activity == "com.example.test.MainActivity"

    def test_extract_detects_native_code(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_features import APKFeaturesExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKFeaturesExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()
        assert result.has_native_code is True
        assert result.has_assets is True

    def test_extract_invalid_apk_returns_none(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_features import APKFeaturesExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        mock_apk.is_valid_APK.return_value = False
        # APKExtractor sets self.apk to the mock_apk directly; _is_valid_apk checks self.apk is not None
        # For invalid APK, set apk to None
        ext = APKFeaturesExtractor(apk_path, logger, exporters=exporters, apk=None)
        # Override _is_valid_apk to simulate parsing failure
        ext.apk = None
        result = ext.extract()
        assert result is None

    def test_extract_handles_missing_version_code(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_features import APKFeaturesExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        mock_apk.get_androidversion_code.return_value = None
        ext = APKFeaturesExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()
        assert result.version_code == 0

    def test_prepare_export_data_clickhouse(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_features import APKFeaturesExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKFeaturesExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        ext.extract()
        result = ext.prepare_export_data("ClickHouseExporter")
        assert result is not None
        data, column_names, column_type_names = result
        assert "sha256" in column_names
        assert "package_name" in column_names
        assert "analysis_date" in column_names
        assert len(column_names) == len(column_type_names)
        assert len(data) == 1  # One row
        assert len(data[0]) == len(column_names)

    def test_prepare_export_data_no_extract(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_features import APKFeaturesExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKFeaturesExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        # Don't call extract() first
        result = ext.prepare_export_data("ClickHouseExporter")
        assert result is None


# ============================================================================
# APKManifestExtractor
# ============================================================================

class TestAPKManifestExtractor:

    def test_tag(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_manifest import APKManifestExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKManifestExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.tag() == "apk_manifest"

    def test_clickhouse_table(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_manifest import APKManifestExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKManifestExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.get_clickhouse_table() == "redb_apk_manifest"

    def test_extract_returns_dataclass(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_manifest import APKManifestExtractor
        from redb.models.dataclasses import APKManifest

        apk_path, mock_apk, logger, exporters = fake_apk_env
        # Setup intent filter mocking
        mock_apk.get_intent_filters.return_value = {}
        ext = APKManifestExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()

        assert isinstance(result, APKManifest)
        assert result.activity_count == 1
        assert result.service_count == 1
        assert result.receiver_count == 1
        assert result.provider_count == 0

    def test_extract_counts_components(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_manifest import APKManifestExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        mock_apk.get_activities.return_value = ["A1", "A2", "A3"]
        mock_apk.get_services.return_value = ["S1", "S2"]
        mock_apk.get_intent_filters.return_value = {}
        ext = APKManifestExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()
        assert result.activity_count == 3
        assert result.service_count == 2


# ============================================================================
# APKPermissionsExtractor
# ============================================================================

class TestAPKPermissionsExtractor:

    def test_tag(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_permissions import APKPermissionsExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKPermissionsExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.tag() == "apk_permissions"

    def test_clickhouse_table(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_permissions import APKPermissionsExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKPermissionsExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.get_clickhouse_table() == "redb_apk_permissions"

    def test_extract_returns_dataclass(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_permissions import APKPermissionsExtractor
        from redb.models.dataclasses import APKPermissions

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKPermissionsExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()

        assert isinstance(result, APKPermissions)
        assert result.total_permission_count == 2
        assert "android.permission.INTERNET" in result.permissions
        assert "android.permission.CAMERA" in result.permissions

    def test_extract_classifies_dangerous(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_permissions import APKPermissionsExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKPermissionsExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()
        # CAMERA is dangerous, INTERNET is normal
        assert result.dangerous_permission_count >= 1
        assert "android.permission.CAMERA" in result.dangerous_permissions

    def test_extract_no_permissions(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_permissions import APKPermissionsExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        mock_apk.get_permissions.return_value = []
        ext = APKPermissionsExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()
        assert result.total_permission_count == 0
        assert result.dangerous_permission_count == 0


# ============================================================================
# APKSignatureExtractor
# ============================================================================

class TestAPKSignatureExtractor:

    def test_tag(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_signature import APKSignatureExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKSignatureExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.tag() == "apk_signature"

    def test_clickhouse_table(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_signature import APKSignatureExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKSignatureExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.get_clickhouse_table() == "redb_apk_signature"

    def test_extract_unsigned_apk(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_signature import APKSignatureExtractor
        from redb.models.dataclasses import APKCodeSigningInfo

        apk_path, mock_apk, logger, exporters = fake_apk_env
        mock_apk.is_signed_v1.return_value = False
        mock_apk.is_signed_v2.return_value = False
        mock_apk.is_signed_v3.return_value = False
        ext = APKSignatureExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()

        assert isinstance(result, APKCodeSigningInfo)

    def test_extract_detects_signature_schemes(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_signature import APKSignatureExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        mock_apk.is_signed_v1.return_value = True
        mock_apk.is_signed_v2.return_value = True
        mock_apk.is_signed_v3.return_value = True
        ext = APKSignatureExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()
        assert 1 in result.signature_scheme_versions
        assert 2 in result.signature_scheme_versions
        assert 3 in result.signature_scheme_versions

    def test_certificate_subject_uses_short_names(self, fake_apk_env):
        """Ensure subject/issuer use RFC 4514 short names (CN=, O=) not long names."""
        from unittest.mock import MagicMock
        from asn1crypto import x509
        from redb.extractors.apk_extractors.apk_signature import APKSignatureExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env

        # Build a real asn1crypto Name so the conversion is exercised
        subject_name = x509.Name.build({
            'country_name': 'US',
            'state_or_province_name': 'California',
            'organization_name': 'Android',
            'common_name': 'Android Debug',
        })

        mock_cert = MagicMock()
        mock_cert.subject = subject_name
        mock_cert.issuer = subject_name
        mock_cert.serial_number = 12345
        mock_cert.not_valid_before = '2020-01-01 00:00:00'
        mock_cert.not_valid_after = '2030-01-01 00:00:00'
        mock_cert.hash_algo = 'sha256'
        mock_cert.public_key.bit_size = 2048
        mock_cert.dump.return_value = b'fake_cert_der_data'

        mock_apk.is_signed_v1.return_value = False
        mock_apk.is_signed_v2.return_value = True
        mock_apk.is_signed_v3.return_value = False
        mock_apk.get_certificates_v2.return_value = [mock_cert]

        ext = APKSignatureExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()

        assert result.apk_signer_subject is not None
        assert 'CN=' in result.apk_signer_subject
        assert 'O=' in result.apk_signer_subject
        assert 'Common Name' not in result.apk_signer_subject
        assert 'Organization' not in result.apk_signer_subject

        # Also check the certificate list
        assert len(result.x509_certificates) == 1
        cert = result.x509_certificates[0]
        assert 'CN=' in cert.subject
        assert 'Common Name' not in cert.subject


# ============================================================================
# APKDexExtractor
# ============================================================================

class TestAPKDexExtractor:

    def test_tag(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_dex import APKDexExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKDexExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.tag() == "apk_dex"

    def test_clickhouse_table(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_dex import APKDexExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKDexExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.get_clickhouse_table() == "redb_apk_dex"

    def test_extract_returns_list(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_dex import APKDexExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        # Mock DEX data access
        mock_apk.get_dex_names.return_value = ["classes.dex"]
        mock_apk.get_all_dex.return_value = [b"dex\n035\x00" + b"\x00" * 100]

        # Mock the androguard DEX parser
        mock_dex_class = MagicMock()
        mock_dex_instance = MagicMock()
        mock_dex_instance.get_classes.return_value = []
        mock_dex_instance.get_methods.return_value = []
        mock_dex_instance.get_strings.return_value = []
        mock_dex_class.return_value = mock_dex_instance

        ext = APKDexExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)

        with patch.dict('sys.modules', {'androguard.core.dex': MagicMock(DEX=mock_dex_class)}):
            result = ext.extract()

        assert result is not None
        assert isinstance(result, list)
        assert len(result) == 1
        assert result[0].filename == "classes.dex"

    def test_extract_computes_tlsh(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_dex import APKDexExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        # Need enough data for TLSH (>50 bytes of varied content)
        import os
        dex_data = os.urandom(256)
        mock_apk.get_dex_names.return_value = ["classes.dex"]
        mock_apk.get_all_dex.return_value = [dex_data]

        mock_dex_class = MagicMock()
        mock_dex_instance = MagicMock()
        mock_dex_instance.get_classes.return_value = []
        mock_dex_instance.get_methods.return_value = []
        mock_dex_instance.get_strings.return_value = []
        mock_dex_instance.get_encoded_methods.return_value = []
        mock_dex_class.return_value = mock_dex_instance

        ext = APKDexExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)

        with patch.dict('sys.modules', {'androguard.core.dex': MagicMock(DEX=mock_dex_class)}):
            result = ext.extract()

        assert result is not None
        assert result[0].tlsh is not None
        assert result[0].tlsh.startswith("T1")

    def test_extract_tlsh_none_for_small_dex(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_dex import APKDexExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        # Too small / uniform for TLSH
        dex_data = b"\x00" * 10
        mock_apk.get_dex_names.return_value = ["classes.dex"]
        mock_apk.get_all_dex.return_value = [dex_data]

        mock_dex_class = MagicMock()
        mock_dex_instance = MagicMock()
        mock_dex_instance.get_classes.return_value = []
        mock_dex_instance.get_methods.return_value = []
        mock_dex_instance.get_strings.return_value = []
        mock_dex_instance.get_encoded_methods.return_value = []
        mock_dex_class.return_value = mock_dex_instance

        ext = APKDexExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)

        with patch.dict('sys.modules', {'androguard.core.dex': MagicMock(DEX=mock_dex_class)}):
            result = ext.extract()

        assert result is not None
        # TLSH returns empty string for insufficient data, which we convert to None
        assert result[0].tlsh is None

    def test_prepare_export_clickhouse_includes_tlsh(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_dex import APKDexExtractor
        from redb.models.dataclasses import APKDexFile

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKDexExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)

        # Manually set dex_files to test export
        ext.dex_files = [APKDexFile(
            filename="classes.dex",
            sha256="aa" * 32,
            class_count=10,
            method_count=50,
            string_count=100,
            tlsh="T1" + "B" * 68,
        )]

        result = ext.prepare_export_data("ClickHouseExporter")
        assert result is not None
        dex_export = result['dex']
        assert 'dex_tlsh' in dex_export['column_names']
        tlsh_idx = dex_export['column_names'].index('dex_tlsh')
        assert dex_export['data'][0][tlsh_idx] == "T1" + "B" * 68
        assert len(dex_export['column_names']) == len(dex_export['column_type_names'])

    def test_extract_no_dex_returns_none(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_dex import APKDexExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        mock_apk.get_dex_names.return_value = []
        mock_apk.get_all_dex.return_value = []
        ext = APKDexExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()
        assert result is None


# ============================================================================
# APKResourceExtractor
# ============================================================================

class TestAPKResourceExtractor:

    def test_tag(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_resources import APKResourceExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKResourceExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.tag() == "apk_resources"

    def test_clickhouse_table(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_resources import APKResourceExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKResourceExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.get_clickhouse_table() == "redb_apk_resources"

    def test_extract_returns_dict(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_resources import APKResourceExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKResourceExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()
        # Returns dict with 'resources' key containing list of APKResource
        assert result is None or isinstance(result, dict)
        if result:
            assert "resources" in result
            assert "total_resource_count" in result
            assert isinstance(result["resources"], list)


# ============================================================================
# APKResourceExtractor — _identify_android_format
# ============================================================================

class TestIdentifyAndroidFormat:
    """Unit tests for Android-specific binary format magic detection."""

    def _make_extractor(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_resources import APKResourceExtractor
        apk_path, mock_apk, logger, exporters = fake_apk_env
        return APKResourceExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)

    def test_axml_magic(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        header = b'\x03\x00\x08\x00' + b'\x00' * 12
        assert ext._identify_android_format(header) == "android_binary_xml"

    def test_arsc_magic(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        header = b'\x02\x00\x0c\x00' + b'\x00' * 12
        assert ext._identify_android_format(header) == "android_resource_table"

    def test_art_prof_magic(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        header = b'pro\x00' + b'\x00' * 12
        assert ext._identify_android_format(header) == "android_art_profile"

    def test_art_profm_magic(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        header = b'prm\x00' + b'\x00' * 12
        assert ext._identify_android_format(header) == "android_art_profile_metadata"

    def test_unknown_magic_returns_none(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        header = b'\xff\xff\xff\xff' + b'\x00' * 12
        assert ext._identify_android_format(header) is None

    def test_short_header_returns_none(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._identify_android_format(b'\x03\x00') is None
        assert ext._identify_android_format(b'') is None

    def test_png_magic_not_matched(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        header = b'\x89PNG\r\n\x1a\n' + b'\x00' * 8
        assert ext._identify_android_format(header) is None


# ============================================================================
# APKResourceExtractor — _is_suspicious_resource
# ============================================================================

class TestIsSuspiciousResource:
    """Unit tests for the layered suspicious resource classification."""

    def _make_extractor(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_resources import APKResourceExtractor
        apk_path, mock_apk, logger, exporters = fake_apk_env
        return APKResourceExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)

    # ── Layer 1: Allowlisted paths ──────────────────────────────────────

    def test_allowlisted_baseline_prof_not_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/dexopt/baseline.prof",
            magika_type="unknown", entropy=7.9,
            android_type=None,
        ) is False

    def test_allowlisted_baseline_profm_not_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/dexopt/baseline.profm",
            magika_type="unknown", entropy=7.9,
            android_type=None,
        ) is False

    # ── Layer 2: Android-specific formats → always benign ───────────────

    def test_axml_not_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="res/layout/activity_main.xml",
            magika_type="gzip", entropy=6.5,
            android_type="android_binary_xml",
        ) is False

    def test_arsc_not_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="res/values/resources.arsc",
            magika_type="unknown", entropy=7.2,
            android_type="android_resource_table",
        ) is False

    def test_art_profile_not_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/custom/baseline.prof",
            magika_type="unknown", entropy=7.8,
            android_type="android_art_profile",
        ) is False

    def test_art_profile_metadata_not_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/other/baseline.profm",
            magika_type="unknown", entropy=7.5,
            android_type="android_art_profile_metadata",
        ) is False

    # ── Layer 3: Image extension / Magika type mismatch ─────────────────

    def test_fake_png_extension_with_non_image_content_is_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="res/raw/payload.png",
            magika_type="zip", entropy=7.2,
            android_type=None,
        ) is True

    def test_fake_jpg_extension_with_unknown_high_entropy_is_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/data.jpg",
            magika_type="unknown", entropy=6.5,
            android_type=None,
        ) is True

    def test_image_extension_mismatch_low_entropy_not_suspicious(self, fake_apk_env):
        """Tiny/low-entropy files with image extensions shouldn't be flagged."""
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="res/drawable/tiny.png",
            magika_type="unknown", entropy=3.0,
            android_type=None,
        ) is False

    # ── Layer 4: Magika-confirmed images → benign ───────────────────────

    def test_confirmed_png_high_entropy_not_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="res/drawable/photo.png",
            magika_type="png", entropy=7.95,
            android_type=None,
        ) is False

    def test_confirmed_webp_high_entropy_not_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="res/drawable/image.webp",
            magika_type="webp", entropy=7.99,
            android_type=None,
        ) is False

    def test_confirmed_jpeg_not_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/photos/bg.jpg",
            magika_type="jpeg", entropy=7.9,
            android_type=None,
        ) is False

    # ── Layer 5: Known suspicious file types ────────────────────────────

    def test_elf_in_assets_is_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/payload",
            magika_type="elf", entropy=5.0,
            android_type=None,
        ) is True

    def test_dex_in_assets_is_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/classes.dex",
            magika_type="dex", entropy=5.5,
            android_type=None,
        ) is True

    def test_shell_script_is_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/run.sh",
            magika_type="shell", entropy=4.0,
            android_type=None,
        ) is True

    def test_zip_in_assets_is_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/data.zip",
            magika_type="zip", entropy=7.5,
            android_type=None,
        ) is True

    def test_jar_in_assets_is_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/plugin.jar",
            magika_type="jar", entropy=6.0,
            android_type=None,
        ) is True

    def test_lzma_in_assets_is_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/blob.lzma",
            magika_type="lzma", entropy=7.9,
            android_type=None,
        ) is True

    # ── Layer 6: High-entropy unrecognized blobs ────────────────────────

    def test_unknown_type_high_entropy_is_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/xyzdata",
            magika_type="unknown", entropy=7.5,
            android_type=None,
        ) is True

    def test_empty_type_high_entropy_is_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/blob.dat",
            magika_type="empty", entropy=7.2,
            android_type=None,
        ) is True

    def test_unknown_type_low_entropy_not_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/config.dat",
            magika_type="unknown", entropy=4.5,
            android_type=None,
        ) is False

    # ── Layer 7: Extreme entropy on non-image recognized types ──────────

    def test_xml_extreme_entropy_is_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="res/raw/config.xml",
            magika_type="xml", entropy=7.9,
            android_type=None,
        ) is True

    def test_txt_extreme_entropy_is_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/readme.txt",
            magika_type="txt", entropy=7.86,
            android_type=None,
        ) is True

    def test_xml_normal_entropy_not_suspicious(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="res/raw/config.xml",
            magika_type="xml", entropy=4.0,
            android_type=None,
        ) is False

    # ── Benign types that should NOT be flagged ─────────────────────────

    def test_html_not_in_suspicious_types(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/index.html",
            magika_type="html", entropy=5.0,
            android_type=None,
        ) is False

    def test_javascript_not_in_suspicious_types(self, fake_apk_env):
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/app.js",
            magika_type="javascript", entropy=5.0,
            android_type=None,
        ) is False

    def test_sqlite_not_in_suspicious_types(self, fake_apk_env):
        """sqlite was intentionally excluded — too many legitimate uses."""
        ext = self._make_extractor(fake_apk_env)
        assert ext._is_suspicious_resource(
            path="assets/data.db",
            magika_type="sqlite", entropy=5.0,
            android_type=None,
        ) is False


# ============================================================================
# APKResourceExtractor — integration with extract()
# ============================================================================

class TestAPKResourceExtractorIntegration:
    """Integration tests: craft ZIP contents and verify end-to-end classification."""

    def test_extract_flags_elf_in_assets(self, tmp_path):
        from redb.extractors.apk_extractors.apk_resources import APKResourceExtractor

        apk_path = _create_fake_apk(str(tmp_path), {
            "assets/payload.bin": b"\x7fELF" + b"\x00" * 100,
        })
        mock_apk = _make_mock_apk()
        logger = MagicMock()

        # Mock Magika to return "elf" for the payload — real Magika needs
        # a valid ELF structure, but we control classification in unit tests.
        mock_magika = MagicMock()
        mock_magika.identify_bytes.return_value = MagicMock(
            output=MagicMock(label="elf")
        )

        ext = APKResourceExtractor(apk_path, logger, exporters=[MagicMock()], apk=mock_apk)
        with patch("magika.Magika", return_value=mock_magika):
            result = ext.extract()
        assert result is not None
        assert result["suspicious_file_count"] >= 1
        sus_paths = [s.path for s in result["suspicious_files"]]
        assert "assets/payload.bin" in sus_paths

    def test_extract_does_not_flag_normal_png(self, tmp_path):
        from redb.extractors.apk_extractors.apk_resources import APKResourceExtractor

        apk_path = _create_fake_apk(str(tmp_path), {
            "res/drawable/icon.png": b"\x89PNG\r\n\x1a\n" + b"\x00" * 50,
        })
        mock_apk = _make_mock_apk()
        logger = MagicMock()

        ext = APKResourceExtractor(apk_path, logger, exporters=[MagicMock()], apk=mock_apk)
        result = ext.extract()
        assert result is not None
        sus_paths = [s.path for s in result["suspicious_files"]]
        assert "res/drawable/icon.png" not in sus_paths

    def test_extract_stores_android_type_override(self, tmp_path):
        from redb.extractors.apk_extractors.apk_resources import APKResourceExtractor

        # AXML magic — Magika would likely misclassify, but stored_type
        # should be "android_binary_xml"
        axml_data = b'\x03\x00\x08\x00' + b'\x00' * 50
        apk_path = _create_fake_apk(str(tmp_path), {
            "res/layout/main.xml": axml_data,
        })
        mock_apk = _make_mock_apk()
        logger = MagicMock()

        ext = APKResourceExtractor(apk_path, logger, exporters=[MagicMock()], apk=mock_apk)
        result = ext.extract()
        assert result is not None
        axml_resources = [r for r in result["resources"]
                          if r.path == "res/layout/main.xml"]
        assert len(axml_resources) == 1
        assert axml_resources[0].filetype_magika == "android_binary_xml"
        assert axml_resources[0].is_suspicious is False

    def test_extract_skips_non_res_non_assets(self, tmp_path):
        from redb.extractors.apk_extractors.apk_resources import APKResourceExtractor

        apk_path = _create_fake_apk(str(tmp_path), {
            "lib/armeabi-v7a/libnative.so": b"\x7fELF" + b"\x00" * 50,
            "META-INF/MANIFEST.MF": b"Manifest-Version: 1.0\n",
        })
        mock_apk = _make_mock_apk()
        logger = MagicMock()

        ext = APKResourceExtractor(apk_path, logger, exporters=[MagicMock()], apk=mock_apk)
        result = ext.extract()
        if result:
            res_paths = [r.path for r in result["resources"]]
            assert "lib/armeabi-v7a/libnative.so" not in res_paths
            assert "META-INF/MANIFEST.MF" not in res_paths

    def test_prepare_export_includes_suspicious_flag(self, tmp_path):
        from redb.extractors.apk_extractors.apk_resources import APKResourceExtractor

        apk_path = _create_fake_apk(str(tmp_path), {
            "assets/evil.bin": b"\x7fELF" + b"\x00" * 100,
            "res/drawable/ok.png": b"\x89PNG\r\n\x1a\n" + b"\x00" * 50,
        })
        mock_apk = _make_mock_apk()
        logger = MagicMock()

        # Map filenames to Magika labels so the ELF payload gets flagged
        def _magika_side_effect(data):
            if data[:4] == b"\x7fELF":
                return MagicMock(output=MagicMock(label="elf"))
            return MagicMock(output=MagicMock(label="png"))

        mock_magika = MagicMock()
        mock_magika.identify_bytes.side_effect = _magika_side_effect

        ext = APKResourceExtractor(apk_path, logger, exporters=[MagicMock()], apk=mock_apk)
        with patch("magika.Magika", return_value=mock_magika):
            ext.extract()
        result = ext.prepare_export_data("ClickHouseExporter")
        assert result is not None
        data, col_names, col_types = result
        assert "is_suspicious" in col_names
        sus_idx = col_names.index("is_suspicious")
        # At least one row should have is_suspicious=1
        sus_values = [row[sus_idx] for row in data]
        assert 1 in sus_values


# ============================================================================
# APKNativeLibExtractor
# ============================================================================

class TestAPKNativeLibExtractor:

    def test_tag(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_native_libs import APKNativeLibExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKNativeLibExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.tag() == "apk_native_libs"

    def test_clickhouse_table(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_native_libs import APKNativeLibExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKNativeLibExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.get_clickhouse_table() == "redb_apk_native_libs"

    def test_extract_finds_native_libs(self, tmp_path):
        from redb.extractors.apk_extractors.apk_native_libs import APKNativeLibExtractor
        from redb.models.dataclasses import APKNativeLib

        # Create APK with a native lib inside
        apk_path = _create_fake_apk(str(tmp_path), {
            "lib/armeabi-v7a/libnative.so": b"\x7fELF" + b"\x00" * 100,
        })
        mock_apk = _make_mock_apk()
        logger = MagicMock()
        exporters = [MagicMock()]

        ext = APKNativeLibExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()
        assert result is not None
        assert isinstance(result, dict)
        assert "native_libs" in result
        assert len(result["native_libs"]) >= 1
        assert isinstance(result["native_libs"][0], APKNativeLib)
        assert result["native_libs"][0].abi == "armeabi-v7a"

    def test_extract_detects_packer_libs(self, tmp_path):
        from redb.extractors.apk_extractors.apk_native_libs import APKNativeLibExtractor

        # Create APK with a known packer lib
        apk_path = _create_fake_apk(str(tmp_path), {
            "lib/armeabi-v7a/libjiagu.so": b"\x7fELF" + b"\x00" * 50,
            "lib/armeabi-v7a/libnormal.so": b"\x7fELF" + b"\x00" * 50,
        })
        mock_apk = _make_mock_apk()
        logger = MagicMock()
        exporters = [MagicMock()]

        ext = APKNativeLibExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()
        assert result is not None
        packer_libs = [lib for lib in result["native_libs"] if lib.is_known_packer]
        assert len(packer_libs) >= 1  # libjiagu.so is a known packer

    def test_extract_no_native_libs(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_native_libs import APKNativeLibExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        # The fake APK has no lib/*.so files
        mock_apk.get_files.return_value = ["classes.dex", "AndroidManifest.xml"]
        ext = APKNativeLibExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()
        assert result is None


# ============================================================================
# APKInconsistencyTestsExtractor
# ============================================================================

class TestAPKInconsistencyTestsExtractor:

    def test_tag(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_inconsistency_tests import APKInconsistencyTestsExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKInconsistencyTestsExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.tag() == "apk_inconsistency_tests"

    def test_clickhouse_table(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_inconsistency_tests import APKInconsistencyTestsExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKInconsistencyTestsExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext.get_clickhouse_table() == "redb_apk_inconsistency_tests"

    def test_extract_returns_dataclass(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_inconsistency_tests import APKInconsistencyTestsExtractor
        from redb.models.dataclasses import APKInconsistencyTests

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKInconsistencyTestsExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()

        assert isinstance(result, APKInconsistencyTests)

    def test_extract_clean_apk_no_anomalies(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_inconsistency_tests import APKInconsistencyTestsExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKInconsistencyTestsExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        result = ext.extract()
        # A clean APK should have mostly False values
        assert result.test_zip_bomb is not None  # Should be set (True or False)


# ============================================================================
# APK workers.py integration — module registry
# ============================================================================

class TestAPKModuleRegistry:

    def test_all_apk_modules_in_registry(self):
        from redb.workers import get_module_by_name

        apk_modules = [
            "APKFeaturesExtractor",
            "APKManifestExtractor",
            "APKPermissionsExtractor",
            "APKSignatureExtractor",
            "APKDexExtractor",
            "APKResourceExtractor",
            "APKNativeLibExtractor",
            "APKInconsistencyTestsExtractor",
        ]
        for name in apk_modules:
            module_class = get_module_by_name(name)
            assert module_class is not None, f"{name} not found in module registry"

    def test_apk_module_classes_correct(self):
        from redb.workers import get_module_by_name
        from redb.extractors.apk_extractors import (
            APKFeaturesExtractor,
            APKManifestExtractor,
            APKPermissionsExtractor,
            APKSignatureExtractor,
            APKDexExtractor,
            APKResourceExtractor,
            APKNativeLibExtractor,
            APKInconsistencyTestsExtractor,
        )

        assert get_module_by_name("APKFeaturesExtractor") is APKFeaturesExtractor
        assert get_module_by_name("APKManifestExtractor") is APKManifestExtractor
        assert get_module_by_name("APKPermissionsExtractor") is APKPermissionsExtractor
        assert get_module_by_name("APKSignatureExtractor") is APKSignatureExtractor
        assert get_module_by_name("APKDexExtractor") is APKDexExtractor
        assert get_module_by_name("APKResourceExtractor") is APKResourceExtractor
        assert get_module_by_name("APKNativeLibExtractor") is APKNativeLibExtractor
        assert get_module_by_name("APKInconsistencyTestsExtractor") is APKInconsistencyTestsExtractor


# ============================================================================
# APK filetype guard — workers.py dispatch
# ============================================================================

class TestAPKWorkerDispatch:

    def test_apk_excluded_from_die_guard(self):
        """APK filetype should be in the exclusion set alongside macho for DIE/BasicProperties/Hash."""
        import redb.workers as workers_mod
        import inspect

        source = inspect.getsource(workers_mod.process_binary_file)
        # The guards should exclude "apk" from DIE, BasicProperties, HashExtractor.
        # The exact tuple may grow as new text-based formats are added (e.g.
        # "javascript"), so we check that "apk" is present in a filetype
        # exclusion guard rather than matching the full tuple literally.
        assert 'filetype not in ("macho", "apk"' in source

    def test_apk_dispatch_branch_exists(self):
        """The APK dispatch branch should exist and registry should provide all APK extractors."""
        import inspect
        import redb.workers as workers_mod
        from redb.extractor_registry import get_filetype_modules

        # Verify the APK branch exists in process_binary_file
        source = inspect.getsource(workers_mod.process_binary_file)
        assert 'elif filetype == "apk"' in source

        # Verify all APK extractors are registered and loadable
        apk_modules = get_filetype_modules("apk")
        apk_names = {m.__name__ for m in apk_modules}
        for expected in [
            "APKFeaturesExtractor", "APKManifestExtractor",
            "APKPermissionsExtractor", "APKSignatureExtractor",
            "APKDexExtractor", "APKResourceExtractor",
            "APKNativeLibExtractor", "APKInconsistencyTestsExtractor",
        ]:
            assert expected in apk_names, f"{expected} not in APK registry"

    def test_apk_dispatch_runs_basic_and_hash(self):
        """The APK dispatch branch should run BasicPropertiesExtractor and HashExtractor."""
        import redb.workers as workers_mod
        import inspect

        source = inspect.getsource(workers_mod.process_binary_file)
        # Find the apk block
        apk_idx = source.index('elif filetype == "apk"')
        apk_block = source[apk_idx:apk_idx + 4000]
        assert "BasicPropertiesExtractor" in apk_block
        assert "HashExtractor" in apk_block


# ============================================================================
# APKExtractor base class
# ============================================================================

class TestAPKExtractorBase:

    def test_binary_property(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_features import APKFeaturesExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKFeaturesExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)

        # binary property should return the file content
        with open(apk_path, "rb") as f:
            expected = f.read()
        assert ext.binary == expected

    def test_is_valid_apk_with_apk(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_features import APKFeaturesExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKFeaturesExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        assert ext._is_valid_apk() is True

    def test_is_valid_apk_without_apk(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_features import APKFeaturesExtractor

        apk_path, _, logger, exporters = fake_apk_env
        ext = APKFeaturesExtractor(apk_path, logger, exporters=exporters, apk=None)
        ext.apk = None
        assert ext._is_valid_apk() is False

    def test_list_files(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_features import APKFeaturesExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKFeaturesExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        files = ext._list_files()
        assert len(files) == 5
        assert "classes.dex" in files

    def test_get_zip_file(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_features import APKFeaturesExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKFeaturesExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)
        zf = ext._get_zip_file()
        assert zf is not None
        zf.close()

    def test_sha256_computed_correctly(self, fake_apk_env):
        from redb.extractors.apk_extractors.apk_features import APKFeaturesExtractor

        apk_path, mock_apk, logger, exporters = fake_apk_env
        ext = APKFeaturesExtractor(apk_path, logger, exporters=exporters, apk=mock_apk)

        # Verify sha256 matches actual file content
        with open(apk_path, "rb") as f:
            expected_sha256 = hashlib.sha256(f.read()).hexdigest()
        assert ext.sha256 == expected_sha256