Hang Wang

229 papers A* 21A 1B 5C 6Misc 3Journal 157Unranked 35
YearRankTypeTitle / Venue / Authors
2026 J jnl
IEEE J. Biomed. Health Informatics
Hang Wang, Mingxing Duan, Yuhuan Lu, Bin Pu, Yue Qin, Shuihua Wang, Kenli Li
2026 J jnl
Concurr. Comput. Pract. Exp.
Shuai Yang, Hang Wang, Liucheng Huang, Xiaojian Ma
2026 J jnl
Neural Networks
Xue Luo, Jiale Huang, Li'an Shen, Hang Wang, Ziqiang Shi
2026 J jnl
Comput. Vis. Image Underst.
Zifan Han, Xuchong Zhang, Hang Wang, Hongbin Sun
2026 A* conf
AAAI
Xunyue Mo, Weibin Wu, Qingrui Tu, Hang Wang, Junxi He, Zibin Zheng
2025 J jnl
CoRR
Hang Wang, Huijie Tang, Ningai Leng, Zhoufan Yu
2025 conf
CICC
Hang Wang, Hao Guo, Xiaohan Zhang, Taiyun Chi
2025 J jnl
Reliab. Eng. Syst. Saf.
Xuanlin Li, Yawei Hu, Hang Wang, Yongbin Liu, Xianzeng Liu, Huitian Lu
2025 J jnl
Comput. Ind. Eng.
Yanjie Zhou, Xiaojin Wang, Hang Wang, Jiang Xu
2025 A* conf
ICLR
Hang Wang, Xin Ye, Feng Tao, Chenbin Pan, Abhirup Mallik, Burhaneddin Yaman, Liu Ren, Junshan Zhang
2025 J jnl
CoRR
Hang Wang, Xin Ye, Feng Tao, Chenbin Pan, Abhirup Mallik, Burhaneddin Yaman, Liu Ren, Junshan Zhang
2025 conf
MLSP
Guangmingmei Yang, Xi Li, Hang Wang, George Kesidis, David J. Miller
2025 J jnl
IEEE Access
Jing Tu, Zhanran Xia, Yongheng Ai, Ruoxin Song, Bin Yang, Changqun Sun, Xiaoyue Chi, Hang Wang
2025 J jnl
IEEE Internet Things J.
Dechen Gao, Shuangyu Cai, Hanchu Zhou, Hang Wang, Iman Soltani, Junshan Zhang
2025 J jnl
Neurocomputing
Hang Wang, Xiaoming Liu, Guan Yang, Sensen Dong, Xingang Hu, Jie Liu
2025 J jnl
Data Intell.
Nana Zhu, Zixian Feng, Hang Wang, Xing Gao, Xinyi Wang, Yuanxing Liu
2025 J jnl
J. Comput. Methods Sci. Eng.
Yuan Yuan, Yongchao Li, Bo Gao, Yichao Bai, Miao Wang, Hang Wang, Lidong Zhou
2025 J jnl
IEEE Access
Lin Li, Qiaoling Yin, Xiaofeng Wang, Hang Wang
2025 J jnl
IEEE Trans. Geosci. Remote. Sens.
Anyu Li, Wei Chen, Xian Wei, Hua Zhang, Hang Wang, Yangkang Chen
2025 J jnl
CoRR
Hang Wang, Dechen Gao, Junshan Zhang
2025 J jnl
IEEE Trans. Instrum. Meas.
Yuanyuan Zhou, Hang Wang, Yongbin Liu, Zhongding Fan, Zheng Cao, Xianzeng Liu
2025 J jnl
Educ. Inf. Technol.
Hang Wang, Xiaorong Hou, Jiaxiu Liu, Xiaoyu Zhou, Mengyao Jiang, Jing Liao
2025 J jnl
CoRR
Hang Wang, Junshan Zhang
2025 A* conf
CVPR
Shibin Mei, Hang Wang, Bingbing Ni
2025 J jnl
CoRR
Shibin Mei, Hang Wang, Bingbing Ni
2025 J jnl
CoRR
Fengyi Wu, Yifei Dong, Zhi-Qi Cheng, Yilong Dai, Guangyu Chen, Hang Wang, Qi Dai, Alexander G. Hauptmann
2025 J jnl
CoRR
Hang Wang, Zhi-Qi Cheng, Chenhao Lin, Chao Shen, Lei Zhang
2025 conf
CPAL
Hang Wang, Qiaoyi Fang, Junshan Zhang
2025 J jnl
CoRR
Hang Wang, Qiaoyi Fang, Junshan Zhang
2025 J jnl
Displays
Zhenbo Yu, Qiaoqiao Jin, Hang Wang, Bingbing Ni, Wenjun Zhang
2025 J jnl
CoRR
Dechen Gao, Hang Wang, Hanchu Zhou, Nejib Ammar, Shatadal Mishra, Ahmadreza Moradipari, Iman Soltani, Junshan Zhang
2025 J jnl
IEEE Trans. Multim.
Hang Wang, Zhi-Qi Cheng, Youtian Du, Lei Zhang
2025 J jnl
IEEE Access
Yujie Shi, Zeyang Tang, Hang Li, Shengcong Wu, Hang Wang
2025 J jnl
Reliab. Eng. Syst. Saf.
Xin Wang, Hang Wang, Minjun Peng
2025 J jnl
IEEE Trans. Geosci. Remote. Sens.
Yunfeng Chen, Yu Jeffrey Gu, Pengfei Zuo, Quan Zhang, Hang Wang, Yangkang Chen
2025 J jnl
CoRR
Hang Wang, Raf Vandebril, Joeri Van der Veken, Nick Vannieuwenhoven
2025 J jnl
IEEE Trans. Artif. Intell.
Hang Wang, David J. Miller, George Kesidis
2025 J jnl
IEEE Trans. Circuits Syst. Video Technol.
Zhenbo Yu, Junjie Wang, Hang Wang, Zhiyuan Zhang, Jinxian Liu, Zefan Li, Bingbing Ni, Wenjun Zhang
2025 Misc conf
ICASSP
Yingmao Miao, Chenhao Lin, Zhengyu Zhao, Hang Wang, Shuai Liu, Chao Shen, Xiaohong Guan
2025 J jnl
IEEE Trans. Medical Imaging
Yuhuan Lu, Guanghua Tan, Bin Pu, Pak-Hei Yeung, Hang Wang, Shengli Li, Jagath C. Rajapakse, Kenli Li
2025 J jnl
IEEE Access
Jing Tu, Yongheng Ai, Zhanran Xia, Ruoxin Song, Bin Yang, Long Qiu, Yitao Yan, Shasha Zhou, Hang Wang
2025 J jnl
Expert Syst. Appl.
Yuanyuan Zhou, Hang Wang, Huaiwang Jin, Yongbin Liu, Xianzeng Liu, Zheng Cao
2025 J jnl
CoRR
Yihao Hu, Pan Wang, Xiaodong Bai, Shijie Cai, Hang Wang, Huazhong Liu, Aiping Yang, Xiangxiang Li, Meiping Ding, Hongyan Liu, Jianguo Yao
2025 B conf
IJCNN
Hang Wang, Menglong Lu, Zhen Huang, Bin Liang, Zhilin Wang, Feng Liu
2025 J jnl
Comput. Geosci.
Shanghua Zhang, Hang Wang, Lele Zhang, Xiangyun Hu
2025 J jnl
IEEE Access
Hao Hu, Jing Tu, Yongheng Ai, Zhanran Xia, Ruoxin Song, Bin Yang, Xinyun Gao, Zhi Li, Fuyuan Liu, Hang Wang
2025 J jnl
IEEE Trans. Multim.
Ruoyi Xue, Cheng Cheng, Hang Wang, Hongbin Sun
2025 J jnl
CoRR
Qiaoyi Fang, Weiyu Du, Hang Wang, Junshan Zhang
2025 conf
TAROS
Hang Wang, Mohsen Zahmatkesh, Martin Stefanec, Farshad Arvin
2025 J jnl
CoRR
Dechen Gao, Boqi Zhao, Andrew Lee, Ian T. Chuang, Hanchu Zhou, Hang Wang, Zhe Zhao, Junshan Zhang, Iman Soltani
2025 J jnl
Entropy
Nuo Li, Hang Wang
2024 J jnl
Microelectron. J.
Hang Wang, Zhenrong Li, Shize Duan, Yanhui Wu, Dawei Dong
2024 J jnl
IEEE Trans. Instrum. Meas.
Yawei Hu, Xuanlin Li, Hang Wang, Yongbin Liu, Xianzeng Liu, Zheng Cao
2024 J jnl
IEEE Robotics Autom. Lett.
Lijun Zhang, Zhe Ma, Jixu Zhou, Kewei Li, Ming Li, Hang Wang, Qiang Zhang, Chen Wang, Kunyuan Lu
2024 J jnl
Int. J. Intell. Syst.
Zhu Yin, Xiaojian Ma, Hang Wang
2024 J jnl
Eng. Appl. Artif. Intell.
Hang Wang, Jiaxu Zhang, Zhu Yin, Liucheng Huang, Jie Wang, Xiaojian Ma
2024 J jnl
CoRR
Cheng Cheng, Hang Wang, Hongbin Sun
2024 C conf
ISCAS
Danqing Zhang, Baoting Li, Hang Wang, Xuchong Zhang, Hongbin Sun
2024 A* conf
NeurIPS
Chende Zheng, Chenhao Lin, Zhengyu Zhao, Hang Wang, Xu Guo, Shuai Liu, Chao Shen
2024 J jnl
IEEE Trans. Netw. Serv. Manag.
Xiwen Jie, Jiangping Han, Guanglei Chen, Hang Wang, Peilin Hong, Kaiping Xue
2024 J jnl
CoRR
Dechen Gao, Shuangyu Cai, Hanchu Zhou, Hang Wang, Iman Soltani, Junshan Zhang
2024 J jnl
IEICE Trans. Inf. Syst.
Zhu Yin, Xiaojian Ma, Hang Wang
2024 J jnl
IEEE Trans. Geosci. Remote. Sens.
Rui Min, Yunfeng Chen, Hang Wang, Yangkang Chen
2024 J jnl
IEEE Trans. Circuits Syst. I Regul. Pap.
Baoting Li, Danqing Zhang, Pengfei Zhao, Hang Wang, Xuchong Zhang, Hongbin Sun, Nanning Zheng
2024 J jnl
IEEE Trans. Inf. Forensics Secur.
Chenhao Lin, Fangbin Yi, Hang Wang, Jingyi Deng, Zhengyu Zhao, Qian Li, Chao Shen
2024 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Minghao Xu, Hang Wang, Bingbing Ni
2024 J jnl
CoRR
Hang Wang, Zhi-Qi Cheng, Youtian Du, Lei Zhang
2024 conf
MLSP
Hang Wang, Zhen Xiang, David J. Miller, George Kesidis
2024 J jnl
IEEE Trans. Instrum. Meas.
Hang Wang, Lei Mao, Yongbin Liu, Jun Tao, Zhiyong Hu, Yuanyuan Zhou
2024 J jnl
Comput. Electron. Agric.
Haitao Wang, Hang Wang, Xiaoyang Liang, Jiandong Wang, Xuefeng Qiu, Chuanjuan Wang, Guangyong Li
2024 A* conf
AAAI
Xuanhong Chen, Hang Wang, Jialiang Chen, Kairui Feng, Jinfan Liu, Xiaohang Wang, Weimin Zhang, Bingbing Ni
2024 conf
MOST
Imran Adham, Hang Wang, Sen Lin, Junshan Zhang
2024 J jnl
Comput. Graph.
Penghui Bu, Hang Wang, Tao Yang, Hong Zhao
2024 J jnl
Comput. Vis. Image Underst.
Hang Wang, Zhenyu Ding, Cheng Cheng, Yuhai Li, Hongbin Sun
2024 A* conf
SP
Hang Wang, Zhen Xiang, David J. Miller, George Kesidis
2024 J jnl
CoRR
Shibin Mei, Hang Wang, Bingbing Ni
2024 conf
ITSC
Song Guo, Shen'ao Wang, Junjie He, Liming Chen, Hang Wang, Hongbin Sun
2024 J jnl
IEEE Trans. Circuits Syst. II Express Briefs
He Dai, Hang Wang, Xuchong Zhang, Hongbin Sun
2024 conf
ECCV (50)
Shibin Mei, Bingbing Ni, Hang Wang, Chenglong Zhao, Fengfa Hu, Zhiming Pi, Bilian Ke
2024 J jnl
Int. Trans. Oper. Res.
Hang Wang, Wen Zhang, Yi He
2024 J jnl
CoRR
Xiao-Jun Wu, Cai-Jun Zhao, Chun Meng, Hang Wang
2024 Misc conf
NSDI
Yazhou Zu, Alireza Ghaffarkhah, Hoang-Vu Dang, Brian Towles, Steven Hand, Safeen Huda, Adekunle Bello, Alexander Kolbasov, Arash Rezaei, Dayou Du, Steve Lacy, Hang Wang, Aaron Wisner, Chris Lewis, Henri Bahini
2024 J jnl
IEEE/ACM Trans. Netw.
Zihao Wang, Hang Wang, Zhuowen Li, Xinghua Li, Yinbin Miao, Yanbing Ren, Yunwei Wang, Zhe Ren, Robert H. Deng
2024 C conf
ISCC
Haoran Chen, Hang Wang, Guanglei Chen, Peilin Hong
2024 J jnl
IEEE J. Biomed. Health Informatics
Yuhuan Lu, Guanghua Tan, Bin Pu, Hang Wang, Bocheng Liang, Kenli Li, Jagath C. Rajapakse
2024 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Xuanhong Chen, Bingbing Ni, Yutian Liu, Naiyuan Liu, Zhilin Zeng, Hang Wang
2024 J jnl
IEEE Trans. Circuits Syst. II Express Briefs
Hang Qian, Dewei Zhang, Qing Liu, Ben-Hua Ma, Hang Wang, Dong-Fang Zhou
2024 A* conf
IJCAI
Zhoulin Ji, Chenhao Lin, Hang Wang, Chao Shen
2024 J jnl
CoRR
Zhoulin Ji, Chenhao Lin, Hang Wang, Chao Shen
2024 J jnl
CoRR
Xi Li, Hang Wang, David J. Miller, George Kesidis
2024 J jnl
Signal Process.
Penghui Bu, Hang Wang, Yihua Dou, Yan Wang, Tao Yang, Hong Zhao
2023 conf
ICC
Kexin Chen, Hang Wang, Peilin Hong
2023 J jnl
IEEE Trans. Very Large Scale Integr. Syst.
Fujun Bai, Song Wang, Xuerong Jia, Yixin Guo, Bing Yu, Hang Wang, Cong Lai, Qiwei Ren, Hongbin Sun
2023 J jnl
IEEE Internet Things J.
Hang Wang, Huansheng Ning, Yujia Lin, Wenxi Wang, Sahraoui Dhelim, Fadi Farha, Jianguo Ding, Mahmoud Daneshmand
2023 J jnl
IEEE Trans. Very Large Scale Integr. Syst.
Baoting Li, Hang Wang, Fujie Luo, Xuchong Zhang, Hongbin Sun, Nanning Zheng
2023 J jnl
CoRR
Hang Wang, Sen Lin, Junshan Zhang
2023 J jnl
Comput. Secur.
Hang Wang, David J. Miller, George Kesidis
2023 conf
NLPCC (1)
Siye Chen, Chunmei Xie, Hang Wang, Shihan Ma, Yarong Liu, Qiuhui Shi, Wenkang Huang, Hongbin Wang
2023 J jnl
Comput. Vis. Image Underst.
Cheng Cheng, Hang Wang, Xiang Liao, Gang Cheng, Hongbin Sun
2023 J jnl
IEEE Internet Things J.
Huansheng Ning, Yujia Lin, Wenxi Wang, Hang Wang, Feifei Shi, Xiaohong Zhang, Mahmoud Daneshmand
2023 A* conf
CVPR
Xiaohang Wang, Xuanhong Chen, Bingbing Ni, Hang Wang, Zhengyan Tong, Yutian Liu
2023 conf
DSIE
Zhichuan Tang, Hang Wang, Zhixuan Cui, Jun Ding, Lingtao Zhang
2023 C conf
SAFEPROCESS
Jiaji Qin, Ling Zhao, Jie Zou, Hang Wang
2023 J jnl
Medical Image Anal.
Lei Cao, Jie Wang, Yuanyuan Zhang, Zhiwei Rong, Meng Wang, Liuying Wang, Jianxin Ji, Youhui Qian, Liuchao Zhang, Hao Wu, Jiali Song, Zheng Liu, Wenjie Wang, Shuang Li, Peiyu Wang, Zhenyi Xu, Jingyuan Zhang, Liang Zhao, Hang Wang, Mengting Sun, Xing Huang, Rong Yin, Yuhong Lu, Ziqian Liu, Kui Deng, Gongwei Wang, Mantang Qiu, Kang Li, Jun Wang, Yan Hou
2023 conf
NLPCC (2)
Chunmei Xie, Hang Wang, Siye Chen, Shihan Ma, Tiantian Huang, Qiuhui Shi, Wenkang Huang, Hongbin Wang
2023 J jnl
Comput. Vis. Image Underst.
Zeyu Hao, Hang Wang, Xuchong Zhang, Yuhai Li, Hongbin Sun
2023 J jnl
CoRR
Chenhao Lin, Fangbin Yi, Hang Wang, Qian Li, Jingyi Deng, Chao Shen
2023 C conf
ISCC
Xiwen Jie, Hang Wang, Runzhou Li, Guanglei Chen, Peilin Hong
2023 J jnl
CoRR
Hang Wang, Zhen Xiang, David J. Miller, George Kesidis
2023 A* conf
AAAI
Xiaohang Wang, Xuanhong Chen, Bingbing Ni, Zhengyan Tong, Hang Wang
2023 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Jinxian Liu, Bingbing Ni, Ye Chen, Zhenbo Yu, Hang Wang
2023 A* conf
NeurIPS
Cheng Cheng, Lin Song, Ruoyi Xue, Hang Wang, Hongbin Sun, Yixiao Ge, Ying Shan
2023 J jnl
CoRR
Cheng Cheng, Lin Song, Ruoyi Xue, Hang Wang, Hongbin Sun, Yixiao Ge, Ying Shan
2023 A* conf
CVPR
Hang Wang, Xuanhong Chen, Bingbing Ni, Yutian Liu, Jinfan Liu
2023 J jnl
CoRR
Hang Wang, Xuanhong Chen, Bingbing Ni, Yutian Liu, Jinfan Liu
2023 J jnl
IEEE Trans. Image Process.
Hang Wang, Youtian Du, Yabin Zhang, Shuai Li, Lei Zhang
2023 J jnl
CoRR
Hang Wang, David J. Miller, George Kesidis
2023 conf
PCCNT
Feifei Qian, Qiu Li, Guozhong Rong, Hang Wang
2023 Misc conf
ICASSP
Hang Wang, Sahar Karami, Ousmane Dia, Hippolyt Ritter, Ehsan Emamjomeh-Zadeh, Jiahui Chen, Zhen Xiang, David J. Miller, George Kesidis
2023 A* conf
SIGIR
Yuanxing Liu, Weinan Zhang, Baohua Dong, Yan Fan, Hang Wang, Fan Feng, Yifan Chen, Ziyu Zhuang, Hengbin Cui, Yongbin Li, Wanxiang Che
2023 J jnl
CoRR
Yuanxing Liu, Weinan Zhang, Baohua Dong, Yan Fan, Hang Wang, Fan Feng, Yifan Chen, Ziyu Zhuang, Hengbin Cui, Yongbin Li, Wanxiang Che
2023 A* conf
ICML
Hang Wang, Sen Lin, Junshan Zhang
2023 J jnl
CoRR
Hang Wang, Sen Lin, Junshan Zhang
2022 J jnl
IEEE Trans. Geosci. Remote. Sens.
Wei Chen, Xingye Liu, Omar M. Saad, Yapo Abolé Serge Innocent Oboué, Liuqing Yang, Hang Wang, Yangkang Chen
2022 J jnl
CoRR
Huansheng Ning, Hang Wang, Wenxi Wang, Xiaozhen Ye, Jianguo Ding, Per Backlund
2022 J jnl
Comput. Biol. Medicine
Jiangting Cheng, Sihong Zhang, Aoyu Fan, Yaohui Li, Peirong Xu, Jiaqi Huang, Minke He, Hang Wang
2022 conf
QRS Companion
Boying Wu, Sigong Zhang, Weirong Tian, Hang Wang
2022 J jnl
IEEE Trans. Intell. Transp. Syst.
Xue Luo, Hang Wang, Yong Deng, Hui Li
2022 A* conf
AAAI
Xirui Yan, Zhenbo Yu, Bingbing Ni, Hang Wang
2022 conf
DTPI
Ziakng Li, Hang Wang, Minjun Peng, Renyi Xu, Yue Yu, Gui Zhou
2022 J jnl
Neurocomputing
Xuchong Zhang, Yongli Zhao, Hang Wang, Han Zhai, Hongbin Sun, Nanning Zheng
2022 J jnl
IEEE Trans. Instrum. Meas.
Hang Wang, Kun Yu, Lei Mao, Qingbo He, Qiang Wu, Zhinong Li
2022 J jnl
IEEE Trans. Geosci. Remote. Sens.
Wei Chen, Liuqing Yang, Hang Wang, Yangkang Chen
2022 J jnl
IEEE Trans. Geosci. Remote. Sens.
Guangtan Huang, Min Bai, Hang Wang, Xingye Liu, Yangkang Chen
2022 J jnl
CoRR
Yujia Lin, Liming Chen, Aftab Ali, Christopher Nugent, Ian Cleland, Rongyang Li, Dazhi Gao, Hang Wang, Yajie Wang, Huansheng Ning
2022 J jnl
IEEE Trans. Instrum. Meas.
Kun Yu, Hang Wang, Lei Mao, Qingbo He, Qiang Wu
2022 J jnl
IEEE Trans. Geosci. Remote. Sens.
Wei Chen, Liuqing Yang, Xingye Liu, Hang Wang, Yangkang Chen
2022 J jnl
CoRR
Xiaohang Wang, Xuanhong Chen, Bingbing Ni, Zhengyan Tong, Hang Wang
2022 A* conf
ACM Multimedia
Junjie Wang, Zhenbo Yu, Zhengyan Tong, Hang Wang, Jinxian Liu, Wenjun Zhang, Xiaoyan Wu
2022 J jnl
CoRR
Xuchong Zhang, Changfeng Sun, Haoliang Han, Hang Wang, Hongbin Sun, Nanning Zheng
2022 conf
AsiaHaptics
Pei Kang, Yan Liu, Hang Wang, Enshan Ouyang, Tao Zeng
2022 conf
ECCV (34)
Hang Wang, Penghao Zhou, Chong Zhou, Zhao Zhang, Xing Sun
2022 J jnl
Comput. Ind. Eng.
Lijun Zhang, Shaowei Fang, Jiayi Xu, Ning Yang, Weijian Guo, Hang Wang, Changliang Li
2022 J jnl
IEEE Trans. Geosci. Remote. Sens.
Hang Wang, Yunfeng Chen, Yapo Abolé Serge Innocent Oboué, Ray Abma, Zhicheng Geng, Sergey Fomel, Yangkang Chen
2022 J jnl
IEEE Trans. Geosci. Remote. Sens.
Yatong Zhou, Jian Yang, Hang Wang, Guangtan Huang, Yangkang Chen
2022 J jnl
IEEE Trans. Geosci. Remote. Sens.
Wei Chen, Omar M. Saad, Hang Wang, Yangkang Chen
2022 J jnl
Neurocomputing
Hang Wang, Cheng Cheng, Xuchong Zhang, Hongbin Sun
2022 J jnl
CoRR
Hang Wang, Sahar Karami, Ousmane Dia, Hippolyt Ritter, Ehsan Emamjomeh-Zadeh, Jiahui Chen, Zhen Xiang, David J. Miller, George Kesidis
2022 J jnl
CoRR
Hang Wang, Zhen Xiang, David J. Miller, George Kesidis
2022 J jnl
Sensors
Hang Wang, Yunfeng Chen, Rui Min, Yangkang Chen
2021 A* conf
CVPR
Linguo Li, Minsi Wang, Bingbing Ni, Hang Wang, Jiancheng Yang, Wenjun Zhang
2021 J jnl
CoRR
Linguo Li, Minsi Wang, Bingbing Ni, Hang Wang, Jiancheng Yang, Wenjun Zhang
2021 conf
ICC Workshops
Hang Wang, Xi Li, Hong Ji, Heli Zhang
2021 conf
SSCI
Huansheng Ning, Hang Wang, Wenxi Wang, Xiaozhen Ye, Jianguo Ding, Per Backlund
2021 J jnl
CoRR
Huansheng Ning, Hang Wang, Yujia Lin, Wenxi Wang, Sahraoui Dhelim, Fadi Farha, Jianguo Ding, Mahmoud Daneshmand
2021 J jnl
IEEE Trans. Instrum. Meas.
Lin Yang, Meng Dai, Hang Wang, Xinsheng Cao, Shiqin Li, Feng Fu, Junying Xia, Zhanqi Zhao
2021 A* conf
NeurIPS
Hang Wang, Sen Lin, Junshan Zhang
2021 J jnl
CoRR
Hang Wang, David J. Miller, George Kesidis
2021 A* conf
ICCV
Minghao Xu, Hang Wang, Bingbing Ni, Riheng Zhu, Zhenbang Sun, Changhu Wang
2021 J jnl
CoRR
Minghao Xu, Hang Wang, Bingbing Ni, Riheng Zhu, Zhenbang Sun, Changhu Wang
2021 J jnl
IEEE Trans. Geosci. Remote. Sens.
Liuqing Yang, Wei Chen, Hang Wang, Yangkang Chen
2021 J jnl
Neural Comput.
Zhen Xiang, David J. Miller, Hang Wang, George Kesidis
2021 J jnl
IEEE Trans. Biomed. Eng.
Lei Wang, Hang Wang, Canhua Xu, Zhenyu Ji, Jianbo Li, Xiuzhen Dong, Xuetao Shi
2021 A conf
AAMAS
Hang Wang, Sen Lin, Hamid Jafarkhani, Junshan Zhang
2021 J jnl
IEEE Trans. Circuits Syst. I Regul. Pap.
Baoting Li, Hang Wang, Xuchong Zhang, Jie Ren, Longjun Liu, Hongbin Sun, Nanning Zheng
2021 J jnl
IEEE Signal Process. Lett.
Guijin Wang, Chenchen Feng, Xiaowei Hu, Hang Wang, Huazhong Yang
2021 J jnl
Comput. Biol. Medicine
Hang Wang, Lei Wang, Lin Yang, Xuetao Shi, Zhihong Wen, Xiuzhen Dong
2021 J jnl
IEEE Trans. Geosci. Remote. Sens.
Hang Wang, Wei Chen, Quan Zhang, Xingye Liu, Shaohuan Zu, Yangkang Chen
2021 B conf
GLOBECOM
Hang Wang, Ming Zhang, Peilin Hong
2021 J jnl
CoRR
Minghao Xu, Hang Wang, Bingbing Ni
2021 conf
APCCAS
Hang Wang, Cheng Cheng, Zeyu Hao, Hongbin Sun
2021 conf
SSIP
Yichuan Zhang, Jiefeng Li, Hang Wang
2021 J jnl
IEEE Trans. Multim.
Hang Wang, Youtian Du, Guangxun Zhang, Zhongmin Cai, Chang Su
2021 J jnl
IET Image Process.
Yunbo Cui, Youtian Du, Xue Wang, Hang Wang, Chang Su
2021 J jnl
IEEE Trans. Geosci. Remote. Sens.
Hang Wang, Guangtan Huang, Wei Chen, Yangkang Chen
2021 J jnl
Comput. Biol. Medicine
Lin Yang, Meng Dai, Shiqin Li, Hang Wang, Xinsheng Cao, Zhanqi Zhao
2021 J jnl
IEEE Trans. Geosci. Remote. Sens.
Hang Wang, Guangtan Huang, Yangkang Chen
2021 J jnl
IEEE Trans. Ind. Electron.
Zhao-Xu Yang, Hai-Jun Rong, Pak-Kin Wong, Plamen Angelov, Zhi-Xin Yang, Hang Wang
2021 A* conf
ICML
Minghao Xu, Hang Wang, Bingbing Ni, Hongyu Guo, Jian Tang
2021 J jnl
CoRR
Minghao Xu, Hang Wang, Bingbing Ni, Hongyu Guo, Jian Tang
2021 A* conf
ICCV
Ye Chen, Jinxian Liu, Bingbing Ni, Hang Wang, Jiancheng Yang, Ning Liu, Teng Li, Qi Tian
2021 J jnl
CoRR
Feifei Shi, Wenxi Wang, Hang Wang, Huansheng Ning
2021 J jnl
CoRR
Xuanhong Chen, Hang Wang, Bingbing Ni
2020 J jnl
IEEE Trans. Circuits Syst. I Regul. Pap.
Hang Wang, Xiang Li, Daqiang Han, Shiquan Yu, Shouyi Yin, Shaojun Wei, Nanning Zheng, Xuchong Zhang, Tiancheng Wang, Wenchang Li, Qiubo Chen, Pengju Ren, Xiaogang Wu, Hongbin Sun, Zhiqiang Jiang
2020 J jnl
IEEE Trans. Neural Networks Learn. Syst.
Guijin Wang, Cairong Zhang, Xinghao Chen, Xiangyang Ji, Jing-Hao Xue, Hang Wang
2020 A* conf
CVPR
Minghao Xu, Hang Wang, Bingbing Ni, Qi Tian, Wenjun Zhang
2020 J jnl
CoRR
Minghao Xu, Hang Wang, Bingbing Ni, Qi Tian, Wenjun Zhang
2020 J jnl
Sensors
Zhiyuan Wu, Hang Wang, Xiping Wang, Hunlong Zheng, Zhiming Chen, Chun Meng
2020 J jnl
CoRR
Hang Wang, Sen Lin, Hamid Jafarkhani, Junshan Zhang
2020 J jnl
IEEE ACM Trans. Comput. Biol. Bioinform.
Hang Wang, Jianing Xi, Minghui Wang, Ao Li
2020 J jnl
IEEE Access
Juan Wu, Min Bai, Dong Zhang, Hang Wang, Guangtan Huang, Yangkang Chen
2020 J jnl
Entropy
Hang Wang, David J. Miller
2020 J jnl
IEEE Trans. Biomed. Eng.
Songde Liu, Hang Wang, Chenxi Zhang, Jiangning Dong, Shengchun Liu, Ronald Xu, Chao Tian
2020 J jnl
IEEE Trans. Multim.
Youtian Du, Xue Wang, Yunbo Cui, Hang Wang, Chang Su
2020 J jnl
CoRR
Hang Wang, Minghao Xu, Bingbing Ni, Wenjun Zhang
2020 conf
ECCV (8)
Hang Wang, Minghao Xu, Bingbing Ni, Wenjun Zhang
2020 conf
MLSP
Zhen Xiang, David J. Miller, Hang Wang, George Kesidis
2020 J jnl
J. Syst. Sci. Complex.
Junying Zhang, Hang Wang, Riquan Zhang, Jiajia Zhang
2020 J jnl
IEEE Access
Hang Wang, Hua Zhang, Yangkang Chen
2020 J jnl
CoRR
Sen Lin, Hang Wang, Junshan Zhang
2019 C conf
ISCAS
Hang Wang, Tiancheng Wang, Yunqi Mi, Hongbin Sun, Nanning Zheng
2019 J jnl
Sensors
Jun Zhu, Ziwu Pan, Hang Wang, Peijie Huang, Jiulin Sun, Fen Qin, Zhenzhen Liu
2019 J jnl
CoRR
Guijin Wang, Cairong Zhang, Xinghao Chen, Xiangyang Ji, Jing-Hao Xue, Hang Wang
2019 J jnl
IEEE Trans. Very Large Scale Integr. Syst.
Hang Wang, Tiancheng Wang, Longjun Liu, Hongbin Sun, Nanning Zheng
2019 J jnl
IEEE Trans. Image Process.
Youtian Du, Hang Wang, Yunbo Cui, Xin Huang
2019 J jnl
Sensors
Xinghao Chen, Guijin Wang, Hengkai Guo, Cairong Zhang, Hang Wang, Li Zhang
2019 conf
BIOSIGNALS
Hang Wang, Mohamed Irfan Mohamed Refai, Bert-Jan F. van Beijnum
2019 B conf
IWQoS
Xiong Wang, Linghe Kong, Jintao Wu, Xiaofeng Gao, Hang Wang, Guihai Chen
2018 conf
APCCAS
Hang Wang, Hongbin Sun, Xuchong Zhang, Qiubo Chen, Pengju Ren, Xiaogang Wu, Shouyi Yin, Zhiqiang Jiang, Xiang Li, Daqiang Han, Shiquan Yu, Shaojun Wei, Nanning Zheng
2017 conf
MLICOM (1)
Hang Wang, Yu Sun, Qingquan Sun
2017 B conf
SMC
Bufan Tong, Juan Chen, Hang Wang, Yakun Yu
2017 C conf
ACC
Hang Wang, Yu-qi Zhu, Juan Chen
2015 conf
O-COCOSDA/CASLRE
Xijing Luo, Jinsong Zhang, Zuyan Wang, Hang Wang
2015 conf
CBD
Baolin Chen, Xiaoyu Li, Hang Lei, Hang Wang
2013 conf
ISNN (2)
Jianyi Liang, Hao Zhang, Ye Liu, Hang Wang, Junhua Li, Liqing Zhang
2013 conf
ICONIP (1)
Hang Wang, Ye Liu, Hao Zhang, Junhua Li, Liqing Zhang
2011 conf
ICPhS
Hong-Rong Yang, Yinting Bai, Hang Wang
2008 conf
ICC
Hang Wang, Jingbo Guo, Zanji Wang
2008 conf
ICIRA (2)
Jiantao Yao, Yulei Hou, Hang Wang, Yongsheng Zhao
2007 conf
ICC
Hang Wang, Jingbo Guo, Zanji Wang
2007 B conf
WCNC
Hang Wang, Jingbo Guo, Zanji Wang
2006 J jnl
IEICE Trans. Electron.
Hang Wang, Lei Zhu
2006 conf
ICECS
Hang Wang, Zanji Wang, Jingbo Guo
2005 J jnl
IEICE Trans. Electron.
Hang Wang, Lei Zhu
2005 J jnl
IEICE Electron. Express
Hang Wang, Lei Zhu
2005 J jnl
IEICE Trans. Electron.
Hang Wang, Lei Zhu
1996 book
Hang Wang, Derek A. Linkens
1994 J jnl
J. Electronic Imaging
Hang Wang, Hong Yan
1993 J jnl
J. Electronic Imaging
Hang Wang, Hong Yan
tests/unit/test_decompile_modules.py
← Index tests/unit/test_decompile_modules.py python
"""
Unit tests for --decompile-modules flag.

Tests that:
1. CLI argument parsing and validation works correctly
2. decompile_modules is threaded through the entire call chain
3. BinaryNinjaDecompiler.analyze_binary() gates extractions per selected modules
4. DecompileBinja.prepare_export_data() filters DB tables per selected modules
"""
import os
import pytest
from unittest.mock import Mock, patch, MagicMock

pytestmark = [pytest.mark.unit]


# ============================================================================
# CLI Argument Parsing Tests
# ============================================================================

class TestDecompileModulesCliArgument:
    """Tests for --decompile-modules CLI argument parsing in start.py."""

    def _parse_args(self, args_list):
        """Helper to parse CLI args without running main()."""
        import argparse

        parser = argparse.ArgumentParser()
        input_group = parser.add_mutually_exclusive_group(required=True)
        input_group.add_argument("--path")
        input_group.add_argument("--s3", action="store_true")
        input_group.add_argument("--s3-solo", metavar="S3_KEY")
        input_group.add_argument("--nomad-job", action="store_true")
        input_group.add_argument("--date", metavar="YYYY-MM-DD")
        input_group.add_argument("--range", nargs=2)
        input_group.add_argument("--analyzed", action="store_true")

        parser.add_argument("--repo")
        parser.add_argument("--index_prefix", default="redb")
        parser.add_argument("-d", "--decompile", action="store_true")
        parser.add_argument("-m", "--modules", default="all")
        parser.add_argument("--decompile-modules", default="all")
        parser.add_argument("--force", action="store_true")
        parser.add_argument("--dry-run", action="store_true")

        return parser.parse_args(args_list)

    def test_decompile_modules_default_all(self):
        """--decompile-modules defaults to 'all'."""
        args = self._parse_args(["--path", "/tmp/test", "--repo", "test"])
        assert args.decompile_modules == "all"

    def test_decompile_modules_single(self):
        """--decompile-modules accepts a single module."""
        args = self._parse_args([
            "--path", "/tmp/test", "--repo", "test",
            "-d", "--decompile-modules", "strings"
        ])
        assert args.decompile_modules == "strings"

    def test_decompile_modules_comma_separated(self):
        """--decompile-modules accepts comma-separated modules."""
        args = self._parse_args([
            "--path", "/tmp/test", "--repo", "test",
            "-d", "--decompile-modules", "cfg,llil,strings"
        ])
        assert args.decompile_modules == "cfg,llil,strings"

    def test_decompile_modules_with_decompile_flag(self):
        """--decompile-modules works with -d flag."""
        args = self._parse_args([
            "--path", "/tmp/test", "--repo", "test",
            "-d", "--decompile-modules", "disassembly"
        ])
        assert args.decompile is True
        assert args.decompile_modules == "disassembly"


# ============================================================================
# Validation Tests
# ============================================================================

class TestDecompileModulesValidation:
    """Tests for --decompile-modules validation logic in start.py."""

    def test_valid_modules_set_parsing(self):
        """Valid comma-separated modules are parsed into a set."""
        VALID = {"all", "decompilation", "disassembly", "cfg", "llil", "strings"}
        raw = "cfg,llil,strings"
        modules_set = {m.strip() for m in raw.split(",")}
        invalid = modules_set - VALID
        assert invalid == set()
        assert modules_set == {"cfg", "llil", "strings"}

    def test_invalid_module_detected(self):
        """Invalid module names are detected."""
        VALID = {"all", "decompilation", "disassembly", "cfg", "llil", "strings"}
        raw = "cfg,invalid_module"
        modules_set = {m.strip() for m in raw.split(",")}
        invalid = modules_set - VALID
        assert invalid == {"invalid_module"}

    def test_all_keyword_as_set(self):
        """'all' is parsed into {'all'} set."""
        raw = "all"
        if raw == "all":
            modules_set = {"all"}
        assert modules_set == {"all"}

    def test_whitespace_handling(self):
        """Whitespace around module names is stripped."""
        raw = " cfg , llil , strings "
        modules_set = {m.strip() for m in raw.split(",")}
        assert modules_set == {"cfg", "llil", "strings"}


# ============================================================================
# Ingestor Parameter Storage Tests
# ============================================================================

class TestIngestorDecompileModules:
    """Tests that Ingestor stores decompile_modules correctly."""

    @patch('builtins.open', MagicMock())
    @patch('redb.ingestor.multiprocessing')
    @patch('redb.ingestor.datetime')
    def test_ingestor_stores_decompile_modules(self, mock_datetime, mock_mp):
        """Ingestor stores the decompile_modules set."""
        mock_mp.Manager.return_value.dict = Mock(side_effect=[{}, {}])
        mock_datetime.today.return_value.strftime.return_value = "20260222"

        from redb.ingestor import Ingestor
        ingestor = Ingestor(
            path="/tmp/test", repository="test", index_prefix="redb",
            decompile_modules={"cfg", "strings"}
        )
        assert ingestor.decompile_modules == {"cfg", "strings"}

    @patch('builtins.open', MagicMock())
    @patch('redb.ingestor.multiprocessing')
    @patch('redb.ingestor.datetime')
    def test_ingestor_defaults_to_all(self, mock_datetime, mock_mp):
        """Ingestor defaults decompile_modules to {'all'} when not provided."""
        mock_mp.Manager.return_value.dict = Mock(side_effect=[{}, {}])
        mock_datetime.today.return_value.strftime.return_value = "20260222"

        from redb.ingestor import Ingestor
        ingestor = Ingestor(
            path="/tmp/test", repository="test", index_prefix="redb"
        )
        assert ingestor.decompile_modules == {"all"}

    @patch('builtins.open', MagicMock())
    @patch('redb.ingestor.multiprocessing')
    @patch('redb.ingestor.datetime')
    def test_ingestor_none_defaults_to_all(self, mock_datetime, mock_mp):
        """Ingestor converts None decompile_modules to {'all'}."""
        mock_mp.Manager.return_value.dict = Mock(side_effect=[{}, {}])
        mock_datetime.today.return_value.strftime.return_value = "20260222"

        from redb.ingestor import Ingestor
        ingestor = Ingestor(
            path="/tmp/test", repository="test", index_prefix="redb",
            decompile_modules=None
        )
        assert ingestor.decompile_modules == {"all"}


# ============================================================================
# Function Chain Threading Tests
# ============================================================================

class TestDecompileModulesThreading:
    """Tests that decompile_modules is correctly threaded through the call chain."""

    @patch('redb.workers.process_binary_file')
    @patch('redb.workers.is_binary_file', return_value=True)
    def test_process_file_internal_passes_decompile_modules(self, mock_is_binary, mock_process):
        """_process_file_internal passes decompile_modules to process_binary_file."""
        from redb.ingestor import _process_file_internal

        mock_process.return_value = (Mock(), "pebin")
        logger = Mock()
        modules = {"cfg", "strings"}

        _process_file_internal(
            "/tmp/test.bin", False, "redb", logger,
            decompile_modules=modules
        )

        mock_process.assert_called_once()
        call_kwargs = mock_process.call_args[1]
        assert call_kwargs["decompile_modules"] == modules

    @patch('redb.workers.process_binary_file')
    @patch('redb.workers.is_binary_file', return_value=True)
    def test_process_file_internal_default_decompile_modules_none(self, mock_is_binary, mock_process):
        """_process_file_internal defaults decompile_modules to None."""
        from redb.ingestor import _process_file_internal

        mock_process.return_value = (Mock(), "pebin")
        logger = Mock()

        _process_file_internal("/tmp/test.bin", False, "redb", logger)

        call_kwargs = mock_process.call_args[1]
        assert call_kwargs["decompile_modules"] is None

    @patch('redb.workers._process_file_internal')
    def test_process_file_passes_decompile_modules(self, mock_internal):
        """process_file passes decompile_modules to _process_file_internal."""
        from redb.workers import process_file

        mock_internal.return_value = (Mock(), "pebin")
        modules = {"llil", "disassembly"}

        with patch('redb.workers.setup_direct_logger', return_value=Mock()):
            process_file(
                "/tmp/test.bin", False, "redb", "/tmp/log", 1, 1,
                decompile_modules=modules
            )

        mock_internal.assert_called_once()
        call_kwargs = mock_internal.call_args[1]
        assert call_kwargs["decompile_modules"] == modules

    @patch('redb.workers._process_file_internal')
    def test_process_s3_file_passes_decompile_modules(self, mock_internal):
        """process_s3_file passes decompile_modules to _process_file_internal."""
        from redb.workers import process_s3_file

        mock_internal.return_value = (Mock(), "pebin")
        modules = {"cfg"}

        with patch('redb.workers.setup_direct_logger', return_value=Mock()), \
             patch('redb.workers.download_s3_object', return_value="/tmp/downloaded.bin"):
            process_s3_file(
                "bucket", "key", "/tmp", False, "redb", "/tmp/log", 1, 1,
                decompile_modules=modules
            )

        mock_internal.assert_called_once()
        call_kwargs = mock_internal.call_args[1]
        assert call_kwargs["decompile_modules"] == modules

    @patch('redb.workers.process_binary_file')
    def test_process_zip_passes_decompile_modules(self, mock_process):
        """process_zip_file passes decompile_modules to process_binary_file."""
        from redb.workers import process_zip_file

        mock_process.return_value = (Mock(), "pebin")
        logger = Mock()
        modules = {"strings", "decompilation"}

        import tempfile
        import zipfile

        with tempfile.NamedTemporaryFile(suffix=".zip", delete=False) as tmp:
            tmp_path = tmp.name

        try:
            with zipfile.ZipFile(tmp_path, 'w') as zf:
                zf.writestr("test.bin", b"\x00" * 100)

            process_zip_file(
                tmp_path, False, "redb", logger, "all",
                decompile_modules=modules
            )

            mock_process.assert_called_once()
            call_kwargs = mock_process.call_args[1]
            assert call_kwargs["decompile_modules"] == modules
        finally:
            os.unlink(tmp_path)

    @patch('redb.workers.process_binary_file')
    def test_process_7zip_passes_decompile_modules(self, mock_process):
        """process_7zip_file passes decompile_modules to process_binary_file."""
        from redb.workers import process_7zip_file

        mock_process.return_value = (Mock(), "pebin")
        logger = Mock()
        modules = {"cfg", "llil"}

        with patch('redb.workers.py7zr') as mock_py7zr:
            mock_zf = Mock()
            mock_py7zr.SevenZipFile.return_value.__enter__ = Mock(return_value=mock_zf)
            mock_py7zr.SevenZipFile.return_value.__exit__ = Mock(return_value=False)

            def fake_extractall(path):
                dest = os.path.join(path, "test.bin")
                with open(dest, "wb") as f:
                    f.write(b"\x00" * 100)

            mock_zf.extractall = fake_extractall

            process_7zip_file(
                "/tmp/test.7z", False, "redb", logger, "all",
                decompile_modules=modules
            )

            if mock_process.called:
                call_kwargs = mock_process.call_args[1]
                assert call_kwargs["decompile_modules"] == modules

    def test_worker_unpacks_decompile_modules(self):
        """worker() correctly unpacks decompile_modules from args tuple."""
        from redb.workers import worker

        modules = {"strings", "cfg"}

        with patch('redb.workers.process_file') as mock_pf, \
             patch('redb.workers.signal'), \
             patch('redb.workers.gc'):
            mock_pf.return_value = (Mock(), "pebin")

            args = (
                "/tmp/test.bin",  # filepath
                True,             # decompile
                "redb",           # index_prefix
                "/tmp/log",       # log_file
                1,                # file_number
                10,               # total_files
                "all",            # selected_modules
                False,            # dry_run
                False,            # yara_scan
                False,            # with_yara
                False,            # force
                modules,          # decompile_modules
            )

            worker(args)

            mock_pf.assert_called_once()
            call_kwargs = mock_pf.call_args[1]
            assert call_kwargs["decompile_modules"] == modules


# ============================================================================
# BinaryNinjaDecompiler._module_selected() Tests
# ============================================================================

class TestModuleSelected:
    """Tests for BinaryNinjaDecompiler._module_selected() helper."""

    def _make_decompiler(self, decompile_modules):
        """Create a minimal BinaryNinjaDecompiler-like object for testing _module_selected."""

        class FakeDecompiler:
            def __init__(self, modules):
                self.decompile_modules = modules

            def _module_selected(self, module_name):
                return "all" in self.decompile_modules or module_name in self.decompile_modules

        return FakeDecompiler(decompile_modules)

    def test_all_selects_everything(self):
        d = self._make_decompiler({"all"})
        assert d._module_selected("strings") is True
        assert d._module_selected("decompilation") is True
        assert d._module_selected("disassembly") is True
        assert d._module_selected("cfg") is True
        assert d._module_selected("llil") is True

    def test_specific_module_selected(self):
        d = self._make_decompiler({"cfg", "strings"})
        assert d._module_selected("cfg") is True
        assert d._module_selected("strings") is True
        assert d._module_selected("decompilation") is False
        assert d._module_selected("disassembly") is False
        assert d._module_selected("llil") is False

    def test_empty_set_selects_nothing(self):
        d = self._make_decompiler(set())
        assert d._module_selected("strings") is False
        assert d._module_selected("decompilation") is False

    def test_single_module(self):
        d = self._make_decompiler({"llil"})
        assert d._module_selected("llil") is True
        assert d._module_selected("cfg") is False
        assert d._module_selected("strings") is False


# ============================================================================
# analyze_binary() Selective Execution Tests
# ============================================================================

class TestAnalyzeBinaryGating:
    """Tests that analyze_binary() gates extraction per decompile_modules.

    Uses a FakeDecompiler to test the gating logic without importing binaryninja.
    """

    def _make_analyze_binary_runner(self, decompile_modules):
        """Create a test harness that simulates the gating logic of analyze_binary()."""
        run_all = "all" in decompile_modules
        run_strings = run_all or "strings" in decompile_modules
        run_decompilation = run_all or "decompilation" in decompile_modules
        run_disassembly = run_all or "disassembly" in decompile_modules
        run_llil = run_all or "llil" in decompile_modules
        run_cfg = run_all or "cfg" in decompile_modules
        need_per_function = run_decompilation or run_disassembly or run_llil or run_cfg

        return {
            "run_strings": run_strings,
            "run_decompilation": run_decompilation,
            "run_disassembly": run_disassembly,
            "run_llil": run_llil,
            "run_cfg": run_cfg,
            "need_per_function": need_per_function,
        }

    def test_all_runs_everything(self):
        r = self._make_analyze_binary_runner({"all"})
        assert r["run_strings"] is True
        assert r["run_decompilation"] is True
        assert r["run_disassembly"] is True
        assert r["run_llil"] is True
        assert r["run_cfg"] is True
        assert r["need_per_function"] is True

    def test_strings_only_skips_per_function_loop(self):
        """Selecting only 'strings' should skip the per-function loop entirely."""
        r = self._make_analyze_binary_runner({"strings"})
        assert r["run_strings"] is True
        assert r["run_decompilation"] is False
        assert r["run_disassembly"] is False
        assert r["run_llil"] is False
        assert r["run_cfg"] is False
        assert r["need_per_function"] is False

    def test_cfg_only_runs_cfg_and_disassembly_in_loop(self):
        """Selecting only 'cfg' should run the per-function loop but skip decompilation/llil/strings."""
        r = self._make_analyze_binary_runner({"cfg"})
        assert r["run_strings"] is False
        assert r["run_decompilation"] is False
        assert r["run_disassembly"] is False  # Not selected (but backbone runs anyway in real code)
        assert r["run_llil"] is False
        assert r["run_cfg"] is True
        assert r["need_per_function"] is True

    def test_decompilation_only(self):
        r = self._make_analyze_binary_runner({"decompilation"})
        assert r["run_decompilation"] is True
        assert r["run_strings"] is False
        assert r["run_cfg"] is False
        assert r["run_llil"] is False
        assert r["need_per_function"] is True

    def test_multiple_modules(self):
        r = self._make_analyze_binary_runner({"cfg", "llil", "strings"})
        assert r["run_strings"] is True
        assert r["run_cfg"] is True
        assert r["run_llil"] is True
        assert r["run_decompilation"] is False
        assert r["run_disassembly"] is False
        assert r["need_per_function"] is True

    def test_disassembly_only(self):
        r = self._make_analyze_binary_runner({"disassembly"})
        assert r["run_disassembly"] is True
        assert r["run_decompilation"] is False
        assert r["run_strings"] is False
        assert r["run_cfg"] is False
        assert r["run_llil"] is False
        assert r["need_per_function"] is True


# ============================================================================
# prepare_export_data() Table Filtering Tests
# ============================================================================

class TestPrepareExportDataFiltering:
    """Tests that prepare_export_data() only includes tables for selected modules.

    Simulates the filtering logic from DecompileBinja.prepare_export_data()
    without importing binaryninja.
    """

    def _get_export_tables(self, decompile_modules):
        """Simulate the table selection logic from prepare_export_data()."""
        run_all = "all" in decompile_modules
        run_decompilation = run_all or "decompilation" in decompile_modules
        run_disassembly = run_all or "disassembly" in decompile_modules
        run_llil = run_all or "llil" in decompile_modules
        run_cfg = run_all or "cfg" in decompile_modules
        run_strings = run_all or "strings" in decompile_modules

        tables = set()
        if run_decompilation:
            tables.update(["decompiled_content", "decompiled_refs"])
        if run_disassembly:
            tables.update(["disassembled_content", "disassembled_refs", "function_similarity_metrics"])
        if run_llil:
            tables.update(["llil_content", "llil_refs"])
        if run_cfg:
            tables.update(["cfg_functions"])
        if run_strings:
            tables.update(["strings_raw"])
        # Errors always included if per-function loop ran
        if run_decompilation or run_disassembly or run_llil or run_cfg:
            tables.add("function_analysis_errors")

        return tables

    def test_all_includes_all_tables(self):
        tables = self._get_export_tables({"all"})
        assert "decompiled_content" in tables
        assert "decompiled_refs" in tables
        assert "disassembled_content" in tables
        assert "disassembled_refs" in tables
        assert "function_similarity_metrics" in tables
        assert "llil_content" in tables
        assert "llil_refs" in tables
        assert "cfg_functions" in tables
        assert "strings_raw" in tables
        assert "function_analysis_errors" in tables

    def test_strings_only_includes_only_strings(self):
        tables = self._get_export_tables({"strings"})
        assert tables == {"strings_raw"}

    def test_cfg_only_includes_cfg_and_errors(self):
        tables = self._get_export_tables({"cfg"})
        assert tables == {"cfg_functions", "function_analysis_errors"}

    def test_decompilation_only_tables(self):
        tables = self._get_export_tables({"decompilation"})
        assert tables == {"decompiled_content", "decompiled_refs", "function_analysis_errors"}

    def test_disassembly_only_tables(self):
        tables = self._get_export_tables({"disassembly"})
        assert tables == {
            "disassembled_content", "disassembled_refs",
            "function_similarity_metrics", "function_analysis_errors"
        }

    def test_llil_only_tables(self):
        tables = self._get_export_tables({"llil"})
        assert tables == {"llil_content", "llil_refs", "function_analysis_errors"}

    def test_combined_cfg_strings_tables(self):
        tables = self._get_export_tables({"cfg", "strings"})
        assert tables == {"cfg_functions", "strings_raw", "function_analysis_errors"}

    def test_no_errors_table_for_strings_only(self):
        """Error table should NOT be included when only strings is selected (no per-function loop)."""
        tables = self._get_export_tables({"strings"})
        assert "function_analysis_errors" not in tables


# ============================================================================
# DecompileBinja Parameter Acceptance Tests
# ============================================================================

class TestDecompileBinjaDecompileModules:
    """Tests that DecompileBinja accepts and stores decompile_modules.

    Since DecompileBinja imports binaryninja (which requires blake3 etc),
    we test the default/init logic in isolation.
    """

    def test_default_decompile_modules(self):
        """decompile_modules defaults to {'all'} when None."""
        modules = None
        result = modules or {"all"}
        assert result == {"all"}

    def test_explicit_decompile_modules(self):
        """Explicit decompile_modules is preserved."""
        modules = {"cfg", "llil"}
        result = modules or {"all"}
        assert result == {"cfg", "llil"}

    def test_empty_set_becomes_all(self):
        """Empty set is falsy and defaults to {'all'}."""
        modules = set()
        result = modules or {"all"}
        assert result == {"all"}


# ============================================================================
# Integration-Style: analyze_binary() Per-Function Gating (Logic Tests)
# ============================================================================

class TestAnalyzeBinaryPerFunctionGating:
    """Test that the per-function extraction gating produces correct results structures.

    These test the logic patterns from analyze_binary() using mock data,
    verifying that:
    - Unselected modules produce empty result lists
    - Selected modules produce populated result lists
    - Disassembly always runs when any per-function module is selected
    - Cross-linkage None handling works when counterparts are skipped
    """

    def _simulate_per_function_results(self, decompile_modules, num_functions=3):
        """Simulate the per-function extraction loop from analyze_binary().

        Returns results dict with the same structure as analyze_binary().
        """
        run_all = "all" in decompile_modules
        run_strings = run_all or "strings" in decompile_modules
        run_decompilation = run_all or "decompilation" in decompile_modules
        run_disassembly = run_all or "disassembly" in decompile_modules
        run_llil = run_all or "llil" in decompile_modules
        run_cfg = run_all or "cfg" in decompile_modules
        need_per_function = run_decompilation or run_disassembly or run_llil or run_cfg

        results = {
            "decompiled": [],
            "disassembled": [],
            "cfg": [],
            "llil": [],
            "errors": [],
            "strings": [],
        }

        if run_strings:
            results["strings"] = [{"string": f"str_{i}"} for i in range(5)]

        if not need_per_function:
            return results

        for i in range(num_functions):
            hlil_json = {"decompiled_function_hash": f"hlil_{i}"} if run_decompilation else None
            disass_json = {"disassembled_function_hash": f"disass_{i}", "disassembled_function_name": f"func_{i}", "disassembled_function_address": i * 100}  # always
            cfg_json = {"function_address": i * 100, "cyclomatic_complexity": 5} if run_cfg else None
            lowlevel_json = {"sha256_llil": f"llil_{i}", "tlsh_llil": "def", "minhash": [1, 2]} if run_llil else None

            # Simulate cross-linkage (same pattern as real code)
            if hlil_json and disass_json:
                hlil_json["disassembled_function_hash"] = disass_json["disassembled_function_hash"]
                disass_json["decompiled_function_hash"] = hlil_json["decompiled_function_hash"]
                results["decompiled"].append(hlil_json)
                if run_disassembly:
                    results["disassembled"].append(disass_json)
            elif hlil_json:
                hlil_json["disassembled_function_hash"] = None
                results["decompiled"].append(hlil_json)
            elif disass_json:
                disass_json["decompiled_function_hash"] = None
                if run_disassembly:
                    results["disassembled"].append(disass_json)

            if lowlevel_json and disass_json:
                lowlevel_json["disassembled_function_hash"] = disass_json["disassembled_function_hash"]
                disass_json["tlsh_llil"] = lowlevel_json.get("tlsh_llil")
                disass_json["minhash"] = lowlevel_json.get("minhash")
            elif lowlevel_json:
                lowlevel_json["disassembled_function_hash"] = None
            elif disass_json:
                disass_json["tlsh_llil"] = None
                disass_json["minhash"] = None

            if lowlevel_json:
                results["llil"].append(lowlevel_json)

            if cfg_json and disass_json:
                cfg_json["disassembled_function_hash"] = disass_json["disassembled_function_hash"]
                disass_json["cyclomatic_complexity"] = cfg_json.get("cyclomatic_complexity")
                results["cfg"].append(cfg_json)
            elif cfg_json:
                cfg_json["disassembled_function_hash"] = None
                results["cfg"].append(cfg_json)

            if disass_json and "cyclomatic_complexity" not in disass_json:
                disass_json["cyclomatic_complexity"] = None

        return results

    def test_all_populates_everything(self):
        r = self._simulate_per_function_results({"all"}, 3)
        assert len(r["decompiled"]) == 3
        assert len(r["disassembled"]) == 3
        assert len(r["cfg"]) == 3
        assert len(r["llil"]) == 3
        assert len(r["strings"]) == 5

    def test_strings_only_populates_strings(self):
        r = self._simulate_per_function_results({"strings"}, 3)
        assert len(r["strings"]) == 5
        assert len(r["decompiled"]) == 0
        assert len(r["disassembled"]) == 0
        assert len(r["cfg"]) == 0
        assert len(r["llil"]) == 0

    def test_cfg_only_populates_cfg_no_disassembly_export(self):
        """With only 'cfg' selected, cfg list is populated but disassembled is empty
        (disassembly runs internally but not exported)."""
        r = self._simulate_per_function_results({"cfg"}, 3)
        assert len(r["cfg"]) == 3
        assert len(r["disassembled"]) == 0  # Not selected for export
        assert len(r["decompiled"]) == 0
        assert len(r["llil"]) == 0
        assert len(r["strings"]) == 0

    def test_cfg_has_disassembled_function_hash_linkage(self):
        """CFG entries get disassembled_function_hash from backbone disassembly."""
        r = self._simulate_per_function_results({"cfg"}, 2)
        for cfg in r["cfg"]:
            assert cfg["disassembled_function_hash"] is not None
            assert cfg["disassembled_function_hash"].startswith("disass_")

    def test_decompilation_only_has_none_disassembly_linkage_when_no_disasm(self):
        """When only decompilation selected, disassembled still runs (backbone)
        so linkage is still available."""
        r = self._simulate_per_function_results({"decompilation"}, 2)
        assert len(r["decompiled"]) == 2
        # Disassembly runs as backbone, so linkage hash is present
        for d in r["decompiled"]:
            assert d["disassembled_function_hash"] is not None

    def test_disassembly_without_llil_has_none_fuzzy_hashes(self):
        """When LLIL is not selected, disassembly records have None fuzzy hashes."""
        r = self._simulate_per_function_results({"disassembly"}, 2)
        for d in r["disassembled"]:
            assert d["tlsh_llil"] is None
            assert d["minhash"] is None

    def test_disassembly_without_decompilation_has_none_decompiled_hash(self):
        """When decompilation is not selected, disassembly has None decompiled_function_hash."""
        r = self._simulate_per_function_results({"disassembly"}, 2)
        for d in r["disassembled"]:
            assert d["decompiled_function_hash"] is None

    def test_disassembly_without_cfg_has_none_cyclomatic(self):
        """When CFG is not selected, disassembly has None cyclomatic_complexity."""
        r = self._simulate_per_function_results({"disassembly"}, 2)
        for d in r["disassembled"]:
            assert d["cyclomatic_complexity"] is None

    def test_all_linkage_populated(self):
        """When all modules run, all cross-linkage fields are populated."""
        r = self._simulate_per_function_results({"all"}, 2)
        for d in r["disassembled"]:
            assert d["decompiled_function_hash"] is not None
            assert d["tlsh_llil"] is not None
            assert d["cyclomatic_complexity"] is not None
        for h in r["decompiled"]:
            assert h["disassembled_function_hash"] is not None
        for c in r["cfg"]:
            assert c["disassembled_function_hash"] is not None
        for ll in r["llil"]:
            assert ll["disassembled_function_hash"] is not None


# ============================================================================
# IOC Extraction Gating by decompile_modules
# ============================================================================

class TestIOCExtractionGating:
    """Tests that IOC extraction only runs when its data sources are present.

    IOCExtractorFromResults consumes in-memory analysis_results['strings']
    and analysis_results['decompiled']. It runs automatically (implicit
    dependency) when 'decompilation' or 'strings' modules produce data.
    It is NOT a standalone selectable module.
    """

    @staticmethod
    def _is_ioc_relevant(decompile_modules):
        """Replicate the gating logic from workers.py."""
        return (
            not decompile_modules
            or "all" in decompile_modules
            or "decompilation" in decompile_modules
            or "strings" in decompile_modules
        )

    def test_all_triggers_ioc(self):
        assert self._is_ioc_relevant({"all"}) is True

    def test_decompilation_triggers_ioc(self):
        assert self._is_ioc_relevant({"decompilation"}) is True

    def test_strings_triggers_ioc(self):
        assert self._is_ioc_relevant({"strings"}) is True

    def test_decompilation_and_strings_triggers_ioc(self):
        assert self._is_ioc_relevant({"decompilation", "strings"}) is True

    def test_cfg_only_skips_ioc(self):
        assert self._is_ioc_relevant({"cfg"}) is False

    def test_disassembly_only_skips_ioc(self):
        assert self._is_ioc_relevant({"disassembly"}) is False

    def test_llil_only_skips_ioc(self):
        assert self._is_ioc_relevant({"llil"}) is False

    def test_cfg_and_disassembly_skips_ioc(self):
        assert self._is_ioc_relevant({"cfg", "disassembly"}) is False

    def test_cfg_and_llil_skips_ioc(self):
        assert self._is_ioc_relevant({"cfg", "llil"}) is False

    def test_cfg_and_decompilation_triggers_ioc(self):
        """If decompilation is included alongside cfg, IOC should run."""
        assert self._is_ioc_relevant({"cfg", "decompilation"}) is True

    def test_disassembly_and_strings_triggers_ioc(self):
        """If strings is included alongside disassembly, IOC should run."""
        assert self._is_ioc_relevant({"disassembly", "strings"}) is True

    def test_none_modules_triggers_ioc(self):
        """When decompile_modules is None (default), IOC should run."""
        assert self._is_ioc_relevant(None) is True

    def test_empty_set_triggers_ioc(self):
        """When decompile_modules is empty set, IOC should run (falsy)."""
        assert self._is_ioc_relevant(set()) is True