
    i=                     D   d Z ddlZddlZddlZddlZddlmZmZ ddlmZ ddl	Z	ej                  j                  d e ee      j                  j                               ddl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)z=Tests for memory-janitor.py - TDD approach (RED phase first).    N)datetime	timedelta)Pathc                   P    e Zd ZdZdeddfdZdeddfdZdeddfdZdeddfdZy)	TestMemoryMdCheckz(Tests for MEMORY.md line count checking.tmp_pathreturnNc           	         |dz  }|j                  dj                  t        d      D cg c]  }d| 	 c}             t        j                  |      }|d   dk(  sJ |d   dk(  sJ |d   d	k(  sJ |d
   t        |      k(  sJ yc c}w )u;   180줄짜리 MEMORY.md는 OK 상태를 반환해야 한다.	MEMORY.md
   line 
line_countlimit   statusOKfileN)
write_textjoinrangemjcheck_memory_mdstrselfr   	memory_mdiresults        R/home/jay/workspace/.worktrees/task-2116-dev1/scripts/tests/test_memory_janitor.py test_check_memory_md_under_limitz2TestMemoryMdCheck.test_check_memory_md_under_limit   s    {*	TYYU3Z'H%s'HIJ##I.l#s***g#%%%h4'''f~Y/// (Is   Bc           	          |dz  }|j                  dj                  t        d      D cg c]  }d| 	 c}             t        j                  |      }|d   dk(  sJ |d   dk(  sJ |d   d	k(  sJ y
c c}w )u@   201줄짜리 MEMORY.md는 WARNING 상태를 반환해야 한다.r   r      r   r   r   r   r   WARNINGNr   r   r   r   r   r   s        r    test_check_memory_md_over_limitz1TestMemoryMdCheck.test_check_memory_md_over_limit!   s    {*	TYYU3Z'H%s'HIJ##I.l#s***g#%%%h9,,, (Is   A4c           	          |dz  }|j                  dj                  t        d      D cg c]  }d| 	 c}             t        j                  |      }|d   dk(  sJ |d   dk(  sJ yc c}w )	uB   정확히 200줄인 MEMORY.md는 OK 상태를 반환해야 한다.r   r   r   r   r   r   r   Nr%   r   s        r    %test_check_memory_md_exactly_at_limitz7TestMemoryMdCheck.test_check_memory_md_exactly_at_limit,   st    {*	TYYU3Z'H%s'HIJ##I.l#s***h4''' (Is   A*c                 `    |dz  }t        j                  |      }|d   dk(  sJ |d   dk(  sJ y)u?   MEMORY.md가 없으면 NOT_FOUND 상태를 반환해야 한다.r   r   	NOT_FOUNDr   r   N)r   r   r   r   missingr   s       r    test_check_memory_md_not_foundz0TestMemoryMdCheck.test_check_memory_md_not_found6   sB    [(##G,h;...l#q(((    )	__name__
__module____qualname____doc__r   r!   r&   r(   r-    r.   r    r   r      sQ    2
0 
0$ 
0	- 	- 	-(d (t ()t ) )r.   r   c                   `    e Zd ZdZdeddfdZdeddfdZdeddfdZdeddfdZdeddfd	Z	y)
TestMemoryFilesReportz0Tests for memory/ directory file size reporting.r   r	   Nc                     |dz  }|j                          t        j                  |      }|d   dk(  sJ |d   dk(  sJ |d   i k(  sJ |d   g k(  sJ y)u>   빈 memory 디렉토리를 graceful하게 처리해야 한다.memorytotal_filesr   total_size_bytesby_directorylargest_filesN)mkdirr   aggregate_memory_filesr   r   
memory_dirr   s       r    test_aggregate_empty_directoryz4TestMemoryFilesReport.test_aggregate_empty_directoryC   su    (
**:6m$)))()Q...n%+++o&",,,r.   c                     |dz  }|j                          |dz  }|j                  d       t        j                  |      }|d   dk(  sJ |d   dk(  sJ t	        |d         dk(  sJ y	)
u9   단일 파일의 크기를 정확히 집계해야 한다.r7   test.mdzhello worldr8      r9      r;   N)r<   r   r   r=   lenr   r   r?   fr   s        r    test_aggregate_single_filez0TestMemoryFilesReport.test_aggregate_single_fileO   s}    (
"	]#**:6m$)))()R///6/*+q000r.   c                    |dz  }|dz  }|dz  }|j                  d       |j                  d       |dz  j                  d       |dz  j                  d	       |d
z  j                  d       t        j                  |      }|d   dk(  sJ |d   dk(  sJ |d   }t	        d |D              sJ t	        d |D              sJ t        d |D              }||   d   dk(  sJ ||   d   dk(  sJ y)uO   여러 하위 디렉토리의 크기를 디렉토리별로 집계해야 한다.r7   reportswhisperT)parentsz
report1.mddAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAz
report2.mdBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBznote.md2CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCr8      r9   i^  r:   c              3   $   K   | ]  }d |v  
 ywrJ   Nr3   .0ks     r    	<genexpr>zLTestMemoryFilesReport.test_aggregate_multiple_directories.<locals>.<genexpr>o        0a9>0   c              3   $   K   | ]  }d |v  
 yw)rK   Nr3   rS   s     r    rV   zLTestMemoryFilesReport.test_aggregate_multiple_directories.<locals>.<genexpr>p   rW   rX   c              3   *   K   | ]  }d |v s|  ywrR   r3   rS   s     r    rV   zLTestMemoryFilesReport.test_aggregate_multiple_directories.<locals>.<genexpr>r   s     =i1n1=s   	files   
size_bytesi,  N)r<   r   r   r=   anynext)r   r   r?   reports_dirwhisper_dirr   dirsreports_keys           r    #test_aggregate_multiple_directoriesz9TestMemoryFilesReport.test_aggregate_multiple_directories\   s&   (
 9, 9,$'$'	|	#//	:	|	#//	:	y	 ,,X6**:6m$)))()S000 n%040000040000=d==K )Q...K .#555r.   c                 :   |dz  }|j                          t        d      D ]$  }|d|ddz  j                  d|dz   z  dz         & t        j                  |      }t        |d	         dk(  sJ |d	   D cg c]  }|d
   	 }}|t        |d      k(  sJ yc c}w )u+   상위 10개 파일만 반환해야 한다.r7      r   02dz.mdXrC   
   r;   r]   T)reverseN)r<   r   r   r   r=   rE   sorted)r   r   r?   r   r   rG   sizess          r    test_largest_files_top_10z/TestMemoryFilesReport.test_largest_files_top_10v   s    (
r 	LAD3s++77q1u8JK	L **:66/*+r111*0*ABQ<BBud3333 Cs   7Bc                 `    |dz  }t        j                  |      }|d   dk(  sJ |d   dk(  sJ y)uG   존재하지 않는 디렉토리도 graceful하게 처리해야 한다.r7   r8   r   r9   N)r   r=   r+   s       r    $test_aggregate_nonexistent_directoryz:TestMemoryFilesReport.test_aggregate_nonexistent_directory   sC    X%**73m$)))()Q...r.   )
r/   r0   r1   r2   r   r@   rH   rd   rm   ro   r3   r.   r    r5   r5   @   sd    :
-t 
- 
-14 1D 16D 6T 644$ 44 4/T /d /r.   r5   c                   p    e Zd ZdZdeddfdZdeddfdZdeddfdZdeddfdZdeddfd	Z	deddfd
Z
y)TestStaleFilesDetectionz3Tests for detecting files not accessed in 30+ days.r   r	   Nc                     |dz  }|j                          |dz  }|j                  d       t        j                  |d      }|g k(  sJ y)u?   최근에 수정된 파일은 stale 목록에 없어야 한다.r7   	recent.mdzrecent content   daysN)r<   r   r   detect_stale_filesrF   s        r    test_no_stale_files_recentz2TestStaleFilesDetection.test_no_stale_files_recent   sO    (
$	%& &&z;||r.   c                 8   |dz  }|j                          |dz  }|j                  d       t        j                         dz
  }t        j                  |||f       t        j                  |d      }t        |      dk(  sJ d|d   d	   v sJ |d   d
   dk\  sJ y)uH   31일 이상 수정되지 않은 파일은 stale로 감지해야 한다.r7   zold-note.mdzold contenti( rt   ru   rC   r   path
days_stale   Nr<   r   timeosutimer   rw   rE   )r   r   r?   old_fileold_timer   s         r    test_detects_old_filesz.TestStaleFilesDetection.test_detects_old_files   s    (
-M* 99;.1
Hh/0&&z;6{aq	& 1111ay&",,,r.   c                     |dz  }|j                          |dz  }|j                  d       t        j                         dz
  }t        j                  |||f       t        j                  |d      }|g k(  sJ y)uI   정확히 30일 된 파일은 stale이 아니다 (30일 초과만 stale).r7   z	border.mdzborder contenti ' rt   ru   N)r<   r   r~   r   r   r   rw   )r   r   r?   border_fileborder_timer   s         r    test_exactly_30_days_not_stalez6TestStaleFilesDetection.test_exactly_30_days_not_stale   st    (
 ;./0 iik^4
{K89&&z;||r.   c                 J   |dz  }|j                          |dz  }|j                  d       |dz  }|j                  d       t        j                         dz
  }t        j                  |||f       t        j                  |d      }t        |      d	k(  sJ d|d
   d   v sJ y)u[   최근 파일과 오래된 파일이 섞여있을 때 오래된 것만 반환해야 한다.r7   rs   recentzstale.mdstalei O rt   ru   rC   r   rz   Nr}   )r   r   r?   r   oldr   r   s          r    test_mixed_filesz(TestStaleFilesDetection.test_mixed_files   s    (
 k)(# :%w99;.1
x*+&&z;6{aVAYv....r.   c                 >   |dz  }|j                          |dz  }|j                  d       t        j                         dz
  }t        j                  |||f       t        j                  |d      }t        |      dk(  sJ t        j                  |d   d	   d
       y)u:   last_modified 필드가 YYYY-MM-DD 형식이어야 한다.r7   zold.mdxi 4 rt   ru   rC   r   last_modifiedz%Y-%m-%dN)
r<   r   r~   r   r   r   rw   rE   r   strptime)r   r   r?   r   r   r   s         r    test_last_modified_formatz1TestStaleFilesDetection.test_last_modified_format   s    (
8#s99;.1
x*+&&z;6{a&)O4jAr.   c                 j    |dz  }|j                          t        j                  |d      }|g k(  sJ y)uP   빈 디렉토리에서 stale 파일 감지는 빈 목록을 반환해야 한다.r7   rt   ru   N)r<   r   rw   r>   s       r    test_stale_empty_directoryz2TestStaleFilesDetection.test_stale_empty_directory   s6    (
&&z;||r.   )r/   r0   r1   r2   r   rx   r   r   r   r   r   r3   r.   r    rq   rq      sz    =
4 
D 
-t - -"t  / /$ /(B$ B4 B4 D r.   rq   c                   `    e Zd ZdZdeddfdZdeddfdZdeddfdZdeddfdZdeddfd	Z	y)
TestDuplicateDetectionz/Tests for detecting duplicate or similar files.r   r	   Nc                 d   |dz  }|j                          |dz  j                  d       |dz  j                  d       t        j                  |g      }|D cg c]  }|d   dk(  s| }}t	        |      dk\  sJ |d	   d
   }t        d |D              sJ t        d |D              sJ yc c}w )uO   하이픈/언더스코어 차이로 유사한 파일명을 감지해야 한다.scriptshealth_score.pyversion1health-score.pyversion2reasonsimilar_namerC   r   r[   c              3   $   K   | ]  }d |v  
 yw)r   Nr3   rT   rG   s     r    rV   zKTestDuplicateDetection.test_hyphen_underscore_similarity.<locals>.<genexpr>        9a$)9rX   c              3   $   K   | ]  }d |v  
 yw)r   Nr3   r   s     r    rV   zKTestDuplicateDetection.test_hyphen_underscore_similarity.<locals>.<genexpr>   r   rX   N)r<   r   r   detect_duplicatesrE   r^   )r   r   scripts_dirr   dsimilarr[   s          r    !test_hyphen_underscore_similarityz8TestDuplicateDetection.test_hyphen_underscore_similarity   s    *	(	(44Z@	(	(44Z@%%{m4$F(~(E1FF7|q   
7#959999959999	 Gs   B-&B-c                    |dz  }|j                          |dz  j                  d       |dz  j                  d       t        j                  |g      }|D cg c]  }|d   dk(  s| }}t	        |      dk\  sJ yc c}w )	uJ   같은 디렉토리 내 동일한 크기의 파일을 감지해야 한다.r   z	file_a.pyzexactly tenz	file_b.pyr   	same_sizerC   Nr<   r   r   r   rE   )r   r   r   r   r   	size_dupss         r    test_same_size_same_directoryz4TestDuplicateDetection.test_same_size_same_directory   s    *	{	"..}=	{	"..}=%%{m4 &E1!H+*DQE	E9~""" Fs   A=&A=c                     |dz  }|j                          |dz  j                  d       |dz  j                  d       t        j                  |g      }|g k(  sJ y)u7   중복이 없을 때 빈 목록을 반환해야 한다.r   zunique_a.pyz	content azunique_b.pyzdifferent content hereN)r<   r   r   r   )r   r   r   r   s       r    test_no_duplicatesz)TestDuplicateDetection.test_no_duplicates	  s_    *	}	$00=	}	$001IJ%%{m4 ||r.   c                 0   |dz  }|dz  }|j                          |j                          |dz  j                  d       |dz  j                  d       t        j                  ||g      }|D cg c]  }|d   dk(  s| }}t	        |      d	k\  sJ y
c c}w )uM   다른 디렉토리에 있는 유사한 이름 파일도 감지해야 한다.dir_adir_bzreport_gen.pyazreport-gen.pybr   r   rC   Nr   )r   r   r   r   r   r   r   s          r     test_similar_name_different_dirsz7TestDuplicateDetection.test_similar_name_different_dirs  s    7"7"		 ,,S1		 ,,S1%%uen5$F(~(E1FF7|q    Gs   .B<Bc                 <    t        j                  g       }|g k(  sJ y)u>   빈 디렉토리 목록도 graceful하게 처리해야 한다.N)r   r   )r   r   r   s      r    test_empty_directoriesz-TestDuplicateDetection.test_empty_directories#  s    %%b)||r.   )
r/   r0   r1   r2   r   r   r   r   r   r   r3   r.   r    r   r      sd    9:$ :4 :
#d 
#t 
#
4 
D 
! !$ !t  r.   r   c                   8    e Zd ZdZddZddZddZddZddZy)	TestRecommendationsz$Tests for recommendation generation.Nc                 p    ddddd}g }g }t        j                  |||      }t        d |D              sJ y)uH   MEMORY.md가 제한 이내이면 OK 권고사항을 생성해야 한다.r   r   r   r   r   r   r   r   c              3   0   K   | ]  }d |v xr d|v   yw)180200Nr3   rT   rs     r    rV   zGTestRecommendations.test_recommendation_memory_md_ok.<locals>.<genexpr>9  s      ;5A:,%1*,;   Nr   generate_recommendationsr^   r   memory_md_checkstale_files
duplicatesrecss        r     test_recommendation_memory_md_okz4TestRecommendations.test_recommendation_memory_md_ok,  sK      	
 
**?KT;d;;;;r.   c                 p    ddddd}g }g }t        j                  |||      }t        d |D              sJ y)uM   MEMORY.md가 제한 초과이면 WARNING 권고사항을 생성해야 한다.r      r   r$   r   c              3   <   K   | ]  }d |v xs
 d|v xs d|v   yw)u   초과r$   u   정리Nr3   r   s     r    rV   zLTestRecommendations.test_recommendation_memory_md_warning.<locals>.<genexpr>H  s)     R8q=CINCh!mCRs   Nr   r   s        r    %test_recommendation_memory_md_warningz9TestRecommendations.test_recommendation_memory_md_warning;  sK      	
 
**?KTRTRRRRr.   c                     ddddd}dddd	d
ddd	g}g }t        j                  |||      }t        d |D              sJ y)uK   stale 파일이 있으면 아카이브 권고사항을 생성해야 한다.r   2   r    r   r   r   r   zold1.mdz
2026-01-01I   )rz   r   r{   zold2.md-   c              3   0   K   | ]  }d |v xr d|v   yw)2u   아카이브Nr3   r   s     r    rV   zFTestRecommendations.test_recommendation_stale_files.<locals>.<genexpr>U  s!     B3!83! 33Br   Nr   r   s        r    test_recommendation_stale_filesz3TestRecommendations.test_recommendation_stale_filesJ  s[    %)cSUVRPRP
 
**?KTBTBBBBr.   c                 |    ddddd}g }ddgdd	g}t        j                  |||      }t        d
 |D              sJ y)uP   중복 파일이 있으면 해당 파일명 권고사항을 생성해야 한다.r   r   r   r   r   zscripts/health_score.pyzscripts/health-score.pyr   )r[   r   c              3   0   K   | ]  }d |v xs d|v   yw)health_scorezhealth-scoreNr3   r   s     r    rV   zETestRecommendations.test_recommendation_duplicates.<locals>.<genexpr>d  s"     L!>Q&=.A*==Lr   Nr   r   s        r    test_recommendation_duplicatesz2TestRecommendations.test_recommendation_duplicatesW  sZ    %)cSUV 45NO(

 **?KTLtLLLLr.   c                 h    ddddd}g }g }t        j                  |||      }t        |      dk\  sJ y)uM   문제가 없을 때도 최소한 하나의 권고사항이 있어야 한다.r   r   r   r   r   rC   N)r   r   rE   r   s        r    test_recommendation_no_issuesz1TestRecommendations.test_recommendation_no_issuesf  s?    %)cSUV
**?KT4yA~~r.   )r	   N)	r/   r0   r1   r2   r   r   r   r   r   r3   r.   r    r   r   )  s!    .<SCMr.   r   c                   @    e Zd ZdZdeddfdZdeddfdZdeddfdZy)TestFullReportz1Integration tests for the full report generation.r   r	   Nc           	         |dz  }|j                          |dz  j                  dj                  t        d      D cg c]  }d| 	 c}             |dz  j                  d       t	        j
                  ||dz  |g      }d	|v sJ d
|v sJ d|v sJ d|v sJ d|v sJ d|v sJ t        j                  |d	          yc c}w )uA   전체 리포트가 올바른 JSON 스키마를 갖춰야 한다.r7   r   r   r   r   rB   ztest contentr?   memory_md_path	scan_dirs	timestampmemory_filesr   r   r   recommendationsN)r<   r   r   r   r   generate_reportr   fromisoformat)r   r   r?   r   r   s        r    test_full_report_structurez)TestFullReport.test_full_report_structuret  s     (
	k	!--diieTVi8X58X.YZ	i	++N;##!%3!l
 f$$$''' F***&&&v%%% F*** 	vk23% 9Ys   C c                     |dz  }|j                          t        j                  ||dz  |g      }t        j                  |      }|J y)u7   전체 리포트가 JSON 직렬화 가능해야 한다.r7   r   r   N)r<   r   r   jsondumps)r   r   r?   r   json_strs        r    "test_full_report_json_serializablez1TestFullReport.test_full_report_json_serializable  sT    (
##!#k1!l
 ::f%###r.   c           	          |dz  }|j                          |dz  }|j                  dj                  t        d      D cg c]  }d| 	 c}             t	        j
                  ||g       }|d   }d|v sJ d	|v sJ d
|v sJ d|v sJ yc c}w )u<   memory_md_check 섹션에 필수 필드가 있어야 한다.r7   r   r   d   r   r   r   r   r   r   r   N)r<   r   r   r   r   r   )r   r   r?   r   r   r   checks          r    'test_full_report_memory_md_check_fieldsz6TestFullReport.test_full_report_memory_md_check_fields  s    (
{*	TYYU3Z'H%s'HIJ##!$
 ()u$$$%5    (Is   B)r/   r0   r1   r2   r   r   r   r   r3   r.   r    r   r   q  s>    ;44 4D 42$4 $D $! ! !r.   r   )r2   r   r   sysr~   r   r   pathlibr   pytestrz   insertr   __file__parentmemory_janitorr   r   r5   rq   r   r   r   r3   r.   r    <module>r      s    C  	 
  (   3tH~,,334 5 +) +)\L/ L/^Y Yx; ;|E EP<! <!r.   