
    RiK              
          d dl Zd dlZd dlZd dlmZ d dlmZ d dlZ ee	      j                  j                  Zej                  j                  d  ee             edz  Zej                   j#                  de      ZeJ ej                   j'                  e      Zej*                  J ej*                  j-                  e       dedee   defd	Zd ded
ee   dz  dee   dz  defdZd!dedededefdZd"dedee   dedee   fdZ G d d      Z G d d      Z  G d d      Z! G d d      Z" G d d      Z# G d d      Z$y)#    N)date)Pathzlearning-analyzer.pylearning_analyzertmp_pathrecordsreturnc                     | dz  }|D cg c]  }t        j                  |       }}|j                  dj                  |      d       |S c c}w )Nzaudit-trail.jsonl
utf-8encoding)jsondumps
write_textjoin)r   r   frliness        U/home/jay/workspace/.worktrees/task-2117-dev1/scripts/tests/test_learning_analyzer.pymake_audit_trailr      sK    &&A$+,qTZZ],E,LL5!GL4H -s   Afilespatternsc                     d}|r|dz  }|D ]  }|d| dz  } |r|dz  }|D ]  }|d| dz  } | dz  }|j                  |d       |S )	N zfiles:
z  - "z"
z
patterns:
zwhitelist.yamlr   r   r   )r   r   r   contentr   ps         r   make_whitelistr       s    G: 	&Aqc~%G	&=  	&Aqc~%G	&##ALL7L+H    min_task_countmin_task_ratioc                 H    d| d| d}| dz  }|j                  |d       |S )Nzmin_task_count: z
min_task_ratio: r
   zthresholds.yamlr   r   r   )r   r    r!   r   r   s        r   make_thresholdsr#   /   s:      00B>BRRTUG$$ALL7L+Hr   	file_pathtask_idsts_basec           
      z    g }t        |      D ]*  \  }}|j                  | dd|z   ddddd|  |dd	       , |S )
NT
   02dz:00:00Zdev1Editz/home/jay/workspace/   tsbottoolfiletask_idschema_version)	enumerateappend)r$   r%   r&   r   itids         r   make_sample_recordsr9   6   sc    GH% 

3 	2a4*G4.yk:"#		


 Nr   c                   0    e Zd ZdefdZdefdZdefdZy)TestLoadWhitelistr   c                 f    t        |dgddg      }t        j                  |      }d|v sd|v sJ y y )Nz(/home/jay/workspace/config/settings.yamlconfig/*ztests/*r   r   r   r   )r   r   load_whitelist)selfr   wl_pathresults       r   test_load_whitelist_normalz,TestLoadWhitelist.test_load_whitelist_normalL   sJ     => ),

 #11':& J&$888$8 r   c                 h    |dz  }t         j                  |      }|i k(  st        |t              sJ y y )Nnonexistent.yaml)r   r?   
isinstancedictr@   r   missingrB   s       r   test_load_whitelist_missingz-TestLoadWhitelist.test_load_whitelist_missingU   s8    //"11':|z&$7777|r   c                     |dz  }|j                  dd       t        j                  |      }|i k(  st        |t              sJ y y )Nz
empty.yamlr   r   r   )r   r   r?   rF   rG   r@   r   r   rB   s       r   test_load_whitelist_emptyz+TestLoadWhitelist.test_load_whitelist_emptyZ   sG    |#	R'*"11!4|z&$7777|r   N)__name__
__module____qualname__r   rC   rJ   rM    r   r   r;   r;   K   s&    94 98D 8
8$ 8r   r;   c                   0    e Zd ZdefdZdefdZdefdZy)TestLoadThresholdsr   c                     t        |dd      }t        j                  |      }|d   dk(  sJ |d   t        j                  d      k(  sJ y )N   g?r    r!   r    r!   )r#   r   load_thresholdspytestapprox)r@   r   th_pathrB   s       r   test_load_thresholds_normalz.TestLoadThresholds.test_load_thresholds_normalg   sQ    !(1SQ"227;&'1,,,&'6==+====r   c                     |dz  }t         j                  |      }|d   dk(  sJ |d   t        j                  d      k(  sJ y )NrE   r       r!   333333?)r   rW   rX   rY   rH   s       r   test_load_thresholds_missingz/TestLoadThresholds.test_load_thresholds_missingm   sN    //"227;&'1,,,&'6==+====r   c                     |dz  }|j                  dd       t        j                  |      }|d   dk(  sJ |d   t        j                  d      k(  sJ y )	Nzpartial.yamlzmin_task_count: 5
r   r   r    rU   r!   r^   )r   r   rW   rX   rY   rL   s       r   test_load_thresholds_partialz/TestLoadThresholds.test_load_thresholds_partials   s^    ~%	*W="2215&'1,,,&'6==+====r   N)rN   rO   rP   r   r[   r_   ra   rQ   r   r   rS   rS   f   s&    >D >>T >>T >r   rS   c                   `    e Zd ZdefdZdefdZdefdZdefdZdefdZdefdZ	defdZ
y	)
TestParseAuditTrailr   c                     t        dddg      }t        ||      }t        ddd      }t        ddd      }t        j	                  |||      }t        |      dk(  sJ y )	N
src/app.pytask-1.1task-2.1           r-   r9   r   r   r   parse_audit_traillenr@   r   r   
trail_path
week_startweek_endrB   s          r   test_parse_normalz%TestParseAuditTrail.test_parse_normal   sa    %lZ4LM%h8
$1%
a$"44ZXV6{ar   c                     t        ddgd      }t        ddgd      }t        |||z         }t        dd	d
      }t        dd	d      }t        j	                  |||      }t        |      dk(  sJ |d   d   dk(  sJ y )Nre   rf   z
2026-04-08)r&   zsrc/other.pyrg   z
2026-04-01rh   ri   rj   rk      r   r3   rl   )r@   r   insideoutsiderp   rq   rr   rB   s           r   !test_parse_excludes_outside_rangez5TestParseAuditTrail.test_parse_excludes_outside_range   s    $\J<V%nzlLY%h0@A
$1%
a$"44ZXV6{aay#z111r   c                     dddddddg}t        ||      }t        dd	d
      }t        dd	d      }t        j                  |||      }t	        |      dk(  sJ y )N2026-04-08T10:00:00Zr+   r,   z/tmp/scratch.pyrf   r-   r.   rh   ri   rj   rk   r   r   r   r   rm   rn   ro   s          r   test_parse_excludes_tmp_pathsz1TestParseAuditTrail.test_parse_excludes_tmp_paths   sr     -)%"#	
 &h8
$1%
a$"44ZXV6{ar   c                     dddddddg}t        ||      }t        dd	d
      }t        dd	d      }t        j                  |||      }t	        |      dk(  sJ y )Nrz   anur,   /home/jay/workspace/src/app.pyrf   r-   r.   rh   ri   rj   rk   r   r{   ro   s          r   test_parse_excludes_anuz+TestParseAuditTrail.test_parse_excludes_anu   sr     -8%"#	
 &h8
$1%
a$"44ZXV6{ar   c                     dddddddddddd	ddg}t        ||      }t        d
dd      }t        d
dd      }t        j                  |||      }t	        |      dk(  sJ y )Nrz   r+   r,   r   unknownr-   r.   z2026-04-08T11:00:00Zr   rh   ri   rj   rk   r   r{   ro   s          r   #test_parse_excludes_unknown_task_idz7TestParseAuditTrail.test_parse_excludes_unknown_task_id   s     -8$"# -8"#
$ &h8
$1%
a$"44ZXV6{ar   c                     t        |g       }t        ddd      }t        ddd      }t        j                  |||      }|g k(  sJ y )Nrh   ri   rj   rk   )r   r   r   rm   )r@   r   rp   rq   rr   rB   s         r   test_parse_empty_filez)TestParseAuditTrail.test_parse_empty_file   sJ    %h3
$1%
a$"44ZXV||r   c                 ~    |dz  }t        ddd      }t        ddd      }t        j                  |||      }|g k(  sJ y )Nnonexistent.jsonlrh   ri   rj   rk   )r   r   rm   )r@   r   rI   rq   rr   rB   s         r   test_parse_missing_filez+TestParseAuditTrail.test_parse_missing_file   sI    00$1%
a$"44Wj(S||r   N)rN   rO   rP   r   rs   rx   r|   r   r   r   r   rQ   r   r   rc   rc      sV     $  2$ 2 d  "   " D  2d  r   rc   c                   \    e Zd ZdddZg g dZd Zd Zd Zd Zd	 Z	d
 Z
d Zd Zd Zd Zy)TestComputeHotspotsr]   r^   rV   r>   c                     t        dg d      }ddd}t        j                  || j                  |      \  }}t	        |      dk(  sJ d|d   d	   v sJ y )
Nre   rf   rg   task-3.1task-4.1r]   皙?rV   ru   zapp.pyr   r2   )r9   r   compute_hotspots_WHITELIST_EMPTYrn   )r@   r   
thresholdshotspots_s        r   test_hotspot_above_thresholdz0TestComputeHotspots.test_hotspot_above_threshold   sa    %l4de()SA
'88$BWBWYcd!8}!!!8A;v....r   c                     t        dddg      }t        j                  || j                  | j                        \  }}t        |      dk(  sJ y )Nre   rf   rg   r   )r9   r   r   r   _THRESHOLDS_DEFAULTrn   )r@   r   r   r   s       r   test_hotspot_below_thresholdz0TestComputeHotspots.test_hotspot_below_threshold   sJ    %lZ4LM'88$BWBWY]YqYqr!8}!!!r   c           
         t        dg d      }d}g }t        d|dz         D ]"  }|j                  dddd	| d
d| ddd       $ ddd}t        j	                  ||z   | j
                  |      \  }}t        |      dk(  sJ y )Nre   rf   rg   r      ri   ru   2026-04-07T10:00:00Zr+   r,   /home/jay/workspace/src/other_.pytask-.1r-   r.   r]         ?rV   r   r9   ranger6   r   r   r   rn   )r@   records_apptotal_task_countextra_recordsr7   r   r   r   s           r   test_hotspot_ratio_checkz,TestComputeHotspots.test_hotspot_ratio_check   s    ),8\]q*Q./ 
	A  0!"<QCsC!&qc}&'	
	 )*SA
'88}9TVZVkVkmwx!8}!!!r   c           
          t        dg d      }g }t        dd      D ]"  }|j                  dddd| d	d
| ddd       $ ddd}t        j	                  ||z   | j
                  |      \  }}t        |      dk(  sJ y )Nre   r   ri      r   r+   r,   r   r   r   r   r-   r.   r]   r   rV   r   r   )r@   r   extrar7   r   r   r   s          r   test_hotspot_and_conditionz.TestComputeHotspots.test_hotspot_and_condition  s    %l4XYq" 
	ALL0!"<QCsC!&qc}&'	
	 )*SA
'885$J_J_akl!8}!!!r   c                     t        dg d      }dhg d}ddd}t        j                  |||      \  }}t        |      dk(  sJ t        |      dk(  sJ y )	Nre   r   r>   r]   r   rV   r   ru   r9   r   r   rn   r@   r   	whitelistr   r   whitelisteds         r   test_whitelist_exclusionz,TestComputeHotspots.test_whitelist_exclusion  sd    %l4de+n"=	()SA
 1 B B7IWa b+8}!!!;1$$$r   c                     t        dg d      }g dgd}ddd}t        j                  |||      \  }}t        |      dk(  sJ t        |      d	k(  sJ y )
Nconfig/settings.yamlr   r=   r>   r]   r   rV   r   ru   r   r   s         r   test_whitelist_pattern_matchingz3TestComputeHotspots.test_whitelist_pattern_matching  se    %&<>no zl;	()SA
 1 B B7IWa b+8}!!!;1$$$r   c                 f   t        dg d      }t        dg d      }ddd}t        j                  ||z   | j                  |      \  }}|D ci c]  }|d   |j	                  d       }}t        d	 |D        d       }t        d
 |D        d       }	|J |	J ||   dk(  sJ ||	   dk(  sJ y c c}w )Nre   r   r   r]   r   rV   r2   typec              3   P   K   | ]  }|d    j                  d      s|d       yw)r2   r   Nendswith.0hs     r   	<genexpr>zGTestComputeHotspots.test_hotspot_type_classification.<locals>.<genexpr>-  s%     Qaqy7I7I%7P&	Q   &
&c              3   P   K   | ]  }|d    j                  d      s|d       yw)r2   z.yamlNr   r   s     r   r   zGTestComputeHotspots.test_hotspot_type_classification.<locals>.<genexpr>.  s%     U69K9KG9T!F)Ur   refactor_candidateconfig_hotspotr9   r   r   r   getnext)
r@   
records_pyrecords_yamlr   r   r   r   typespy_file	yaml_files
             r    test_hotspot_type_classificationz4TestComputeHotspots.test_hotspot_type_classification'  s    (7gh
*+ACst()SA
'88l9RTXTiTikuv!3;<a6AEE&M)<<Q8QSWXUXUW[\	"""$$$W~!5555Y#3333 =   B.c                 f   t        dg d      }t        dg d      }ddd}t        j                  ||z   | j                  |      \  }}|D ci c]  }|d   |j	                  d	       }}t        d
 |D        d       }t        d |D        d       }	|J |	J ||   dk(  sJ ||	   dk(  sJ y c c}w )Nzsrc/high.py)rf   rg   r   r   ztask-5.1zsrc/medium.pyr   r]   r   rV   r2   priorityc              3   6   K   | ]  }d |d   v s|d     yw)zhigh.pyr2   NrQ   r   s     r   r   zKTestComputeHotspots.test_hotspot_priority_classification.<locals>.<genexpr><  s     Pai9O!F)P   
c              3   6   K   | ]  }d |d   v s|d     yw)z	medium.pyr2   NrQ   r   s     r   r   zKTestComputeHotspots.test_hotspot_priority_classification.<locals>.<genexpr>=  s     T!;!F);SAfITr   highmediumr   )
r@   records_highrecords_mediumr   r   r   r   priority_map	high_filemedium_files
             r   $test_hotspot_priority_classificationz8TestComputeHotspots.test_hotspot_priority_classification4  s    *=:vw,_>bc()SA
'88>)4+@+@*
! ?GG&	155#44GGPXPRVW	TxTVZ[$$$&&&I&&000K(H444 Hr   c                 $   g d}t        d|      }ddd}t        j                  || j                  |      \  }}t	        |      dk(  sJ d|d   v s	d	|d   v sJ |d   j                  d      xs |d   j                  d	      }|D ]  }||v rJ  y )
Nr   re   r]   r   rV   ru   r%   r   tasks)r9   r   r   r   rn   r   )r@   r%   r   r   r   r   	task_listr8   s           r   test_hotspot_includes_task_listz3TestComputeHotspots.test_hotspot_includes_task_listC  s    C%lH=()SA
'88$BWBWYcd!8}!!!Xa[(Gx{,BBBQKOOJ/K8A;??73K	 	$C)###	$r   c                 |    t         j                  g | j                  | j                        \  }}|g k(  sJ |g k(  sJ y )N)r   r   r   r   )r@   r   r   s      r   test_empty_recordsz&TestComputeHotspots.test_empty_recordsN  sB     1 B B2tG\G\^b^v^v w+2~~b   r   N)rN   rO   rP   r   r   r   r   r   r   r   r   r   r   r   r   rQ   r   r   r   r      sJ    -.#F!#4/"
"&"$%%45	$!r   r   c                       e Zd Z eddd      Z eddd      Zddedededed	ef
d
Z	de
fdZde
fdZde
fdZde
fdZde
fdZde
fdZy)TestGenerateReportrh   ri   rj      r$   
task_countr   total_tasksr   c           	      l    |||r||z  ndt        d|dz         D cg c]  }d| d
 c}d||dS c c}w )Nr   ru   r   r   r   )r2   r   
task_ratior%   r   r   r   )r   )r@   r$   r   r   r   r7   s         r   _make_hotspotz TestGenerateReport._make_hotspot]  sN    $6A*{2q05aa0HI152I( &
 	
 Js   1
r   c                     | j                  d      g}t        j                  |g | j                  | j                  d|      }|j                         sJ y )Nr   r)   )r   r   generate_report_WEEK_START	_WEEK_ENDexists)r@   r   r   output_paths       r   test_report_createdz&TestGenerateReport.test_report_createdh  sQ    &&'GHI'77"dFVFVX\XfXfhjltu!!###r   c                     | j                  d      g}t        j                  |g | j                  | j                  d|      }|j                  d      }d|v sJ d|v sJ y )Nr   r)   r   r   
2026-04-07z
2026-04-13r   r   r   r   r   	read_textr@   r   r   r   r   s        r   test_report_contains_headerz.TestGenerateReport.test_report_contains_headerm  sn    &&'GHI'77"dFVFVX\XfXfhjltu'''9w&&&w&&&r   c                     t         j                  g g | j                  | j                  d|      }|j	                  d      }d|v sJ d|v sJ d|v sJ y )Nr   r   r   u   학습 기능 v1u   에러 유사도 미지원u	   v2 예정)r   r   r   r   r   )r@   r   r   r   s       r   "test_report_contains_v1_limitationz5TestGenerateReport.test_report_contains_v1_limitationt  sh    '77B@P@PRVR`R`bcemn'''9!W,,,+w666g%%%r   c                     | j                  d      g}t        j                  |g | j                  | j                  d|      }|j                  d      }d|v sJ y )Nr   r)   r   r   z**status**: pendingr   r   s        r   #test_report_contains_hotspot_statusz6TestGenerateReport.test_report_contains_hotspot_status{  s`    &&'GHI'77"dFVFVX\XfXfhjltu'''9$///r   c                     | j                  d      g}t        j                  |g | j                  | j                  d|      }|j                  d      }d|j                         v sd|v sJ y y )Nr   r)   r   r   summaryu   요약)r   r   r   r   r   r   lowerr   s        r   test_report_contains_summaryz/TestGenerateReport.test_report_contains_summary  ss    &&'GHI'77"dFVFVX\XfXfhjltu'''9GMMO+x7/BBB/B+r   c                     t         j                  g g | j                  | j                  d|      }|j                  j                  d      sJ |j                  j                  d      sJ d|j                  v sJ y )Nr   zweekly-z.md2026)r   r   r   r   name
startswithr   )r@   r   r   s      r   test_report_filename_formatz.TestGenerateReport.test_report_filename_format  ss    '77B@P@PRVR`R`bcemn**9555((///)))))r   N)ri   r   r)   )rN   rO   rP   r   r   r   strintrG   r   r   r   r   r   r   r   r   rQ   r   r   r   r   Y  s    tQ"KT1b!I	
s 	
 	
3 	
fi 	
sw 	
$D $
'D '&4 &0D 0CT C*D *r   r   c                   L    e Zd Z eddd      Z eddd      ZdefdZdefdZy)	TestCLIrh   ri   rj   r   r   c                 z   t        dg d      t        ddg      z   }t        ||      }t        |      }t        |      }|dz  }|j	                          t
        j                  || j                  | j                        }t
        j                  |      }t
        j                  |      }	t
        j                  |||	      \  }
}t        |D ch c]  }|d   	 c}      }t
        j                  |
|| j                  | j                  ||      }|j                         sJ |j                  d      }d	|v sJ y c c}w )
Nz
src/hot.pyr   zsrc/normal.pyrf   reportsr3   r   r   zhot.py)r9   r   r   r#   mkdirr   rm   r   r   r?   rW   r   rn   r   r   r   )r@   r   r   rp   rA   rZ   
output_dirparsedr   r   r   r   r   r   report_pathr   s                   r   test_cli_with_sample_dataz!TestCLI.test_cli_with_sample_data  s1   %J
*>? &h8
 *!(+	)
"44ZAQAQSWSaSab%44W=	&66w?
 1 B B69V` a+8A1Y<89'77k4#3#3T^^[R\
 !!###'''97""" 9s   D8c                 B   |dz  }t        |      }t        |      }|dz  }|j                          	 t        j	                  || j
                  | j                        }|g k(  sJ t        j                  |      }t        j                  |      }t        j                  |||      \  }	}
t        j                  |	|
| j
                  | j                  d|      }|j                         sJ y # t        $ r Y y t        $ r"}t        j                  d|        Y d }~y d }~ww xY w)Nr   r  r   u7   audit-trail 없을 때 예상치 못한 예외 발생: )r   r#   r  r   rm   r   r   r?   rW   r   r   r   
SystemExit	ExceptionrX   fail)r@   r   rI   rA   rZ   r  r	  r   r   r   r   r
  es                r   test_cli_missing_audit_trailz$TestCLI.test_cli_missing_audit_trail  s   00 *!(+	)
	W&88$BRBRTXTbTbcFR<<)88AI*::7CJ$5$F$FvyZd$e!Hk+;;+t'7'7JK %%''' 	 	WKKQRSQTUVV	Ws   B6C) )	D4D<DDN)	rN   rO   rP   r   r   r   r   r  r  rQ   r   r   r  r    s8    tQ"KT1b!I#$ #,WT Wr   r  )NN)r]   r^   )r   )%importlib.util	importlibr   sysdatetimer   pathlibr   rX   __file__parent_SCRIPTS_DIRpathinsertr  _MODULE_PATHutilspec_from_file_locationspecmodule_from_specr   loaderexec_modulelistrG   r   r   r  floatr#   r9   r;   rS   rc   r   r   r  rQ   r   r   <module>r%     s     
   H~$$++ 3|$ %44~~--.A<P NN33D9 {{    ) *t d4j T T $s)d*: TRUYY]M] im d C U ]a 3 $s) c ]abf]g *8 86> >4Z ZDo! o!n2* 2*t.W .Wr   