
    i=                     `   d Z ddlZddlZddlZddlZddlmZ ddlZej                  j                  dd       ddl
mZ  ej                  d      Z ej                  d      Z ej                  d      Zdd	ed
edefdZdd	ed
edefdZd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zy)u   TDD RED phase - MemoryIndexer 테스트

TC01 ~ TC12: SQLite FTS5 기반 메모리 인덱서 전체 기능 검증.
이 단계에서는 utils/memory_indexer.py 미구현 상태이므로
ImportError만 발생해야 한다 (RED phase).
    N)Pathz/home/jay/workspace)MemoryIndexeruc      ---
    date: "2026-04-05"
    session: 1
    team_id: "dev3"
    task_id: "task-9999"
    tags: [auto-compact, pre-compact]
    auto_generated: true
    ---
    ## 수행한 작업
    - 메모리 인덱서 TDD RED phase 작성
    - SQLite FTS5 테이블 설계 검토

    ## 피드백 및 수정 지시
    - 한국어 검색 성능 확인 필요
u      ---
    name: 위임 규칙 종합
    description: 파일 기반 위임, 논리적 팀, 한정승인 등
    type: feedback
    team_id: "dev3"
    ---
    ### 파일 기반 위임 (절대 규칙)
    - 지시 내용 → 파일 작성 → `--task-file`로 전달.
    - 100자 이내만 `--task` 허용.

    ### 논리적 팀
    - 마케팅/컨설팅/출판/디자인 라우팅 규칙 준수.
uh      ---
    name: 위임 규칙 종합 (업데이트)
    description: 파일 기반 위임, 논리적 팀, 한정승인 등 - 수정됨
    type: feedback
    team_id: "dev3"
    ---
    ### 파일 기반 위임 (절대 규칙, 수정)
    - 지시 내용 → 파일 작성 → `--task-file`로 전달.
    - 200자 이내까지 `--task` 허용으로 변경.
	directoryfilenamereturnc                 >    | |z  }|j                  t        d       |S )u+   임시 디렉토리에 diary 파일 생성.utf-8encoding)
write_textDIARY_CONTENTr   r   fs      J/home/jay/workspace/.worktrees/task-2116-dev1/tests/test_memory_indexer.pymake_diary_filer   F   s!    HALLL1H    c                 >    | |z  }|j                  t        d       |S )u,   임시 디렉토리에 memory 파일 생성.r	   r
   )r   MEMORY_CONTENTr   s      r   make_memory_filer   M   s!    HALL'L2Hr   c                    t        | dz        }t        |      }|j                          t        |      j	                         sJ d       t        j                  |      }|j                         }|j                  d       |j                         J d       |j                  d       |j                         J d       |j                          y)	uS   DB 파일이 생성되고 memories + memories_fts 테이블이 존재해야 한다.test_index.dbdb_pathu*   DB 파일이 생성되지 않았습니다.zESELECT name FROM sqlite_master WHERE type='table' AND name='memories'Nu0   memories 테이블이 존재하지 않습니다.zISELECT name FROM sqlite_master WHERE type='table' AND name='memories_fts'u@   memories_fts FTS5 가상 테이블이 존재하지 않습니다.)
strr   closer   existssqlite3connectcursorexecutefetchone)tmp_pathr   indexerconnr   s        r   test_TC01_db_creationr%   X   s    (_,-GG,GMMO =!O#OO!??7#D[[]F NNO ??(\*\\( NNS ??(l*ll(JJLr   c                 :   t        | dz        }t        |       }t        |      }|j                  t        |            }|j	                          |J d       |j                  d      dk(  sJ d|j                  d              |j                  d      d	k(  sJ d
|j                  d              |j                  dd      }t        |t               r|ndj                  |      }d|v s
J d|        d|v s
J d|        |j                  d      sJ d       y)u]   diary 파일에서 date, session, team_id, task_id, tags를 올바르게 파싱해야 한다.r   r   N,   _parse_file()이 None을 반환했습니다.team_iddev3u   team_id 불일치: task_idz	task-9999u   task_id 불일치: tags ,zauto-compactu   tags에 'auto-compact' 없음: zpre-compactu   tags에 'pre-compact' 없음: contentu   content가 비어있습니다.)r   r   r   _parse_filer   get
isinstancejoin)r"   r   
diary_filer#   parsedtags_rawtags_strs          r   test_TC02_parse_diary_filer7   w   s(   (_,-G *JG,G  Z1FMMOMMM::i F*Y.A&**YBWAX,YY*::i K/^3FvzzR[G\F]1^^/zz&"%H%h4x#((8:LHX%S)H
'SS%H$Q(Fxj&QQ$::i B"BB r   c                    t        | dz        }t        |       }t        |      }|j                  t        |            }|j	                          |J d       |j                  d      xs |j                  d      }|sJ d       d|v s
J d	|        |j                  d
      dk(  sJ d|j                  d
              y)u]   메모리 파일에서 name(→title), type, description을 올바르게 파싱해야 한다.r   r   Nr'   titlenameu*   title(또는 name) 필드가 없습니다.   위임 규칙u!   title에 '위임 규칙' 없음: typefeedbacku   type 불일치: )r   r   r   r/   r   r0   )r"   r   mem_filer#   r4   r9   s         r   test_TC03_parse_memory_filer?      s    (_,-G)HG,G  X/FMMOMMMJJw56::f#5E>>>5e#P'H%PP#::f+T/?

6@R?S-TT+r   c                    t        | dz        }t        |       }t        |      }|j                  t        |            }|j	                          |dk(  sJ d|d       t        j                  |      }|j                         }|j                  dt        |      f       |j                         d   }|j	                          |dk(  s
J d	|        y
)u[   단일 파일을 인덱싱하면 memories 테이블에 레코드가 삽입되어야 한다.r   r   indexedu"   index_file() 반환값 불일치: u    (기대: 'indexed')z1SELECT COUNT(*) FROM memories WHERE file_path = ?r      u'   DB에 레코드가 없습니다. count=N)
r   r   r   
index_filer   r   r   r   r    r!   )r"   r   r3   r#   resultr$   r   counts           r   test_TC04_index_single_filerF      s    (_,-G *JG,GJ0FMMOYc"DVJNb cc ??7#D[[]F
NNFZHZ[OOa EJJLA:H@HH:r   c                    t        | dz        }t        |       }t        |      }|j                  t        |            }|j                  t        |            }|j	                          |dk(  s
J d|       |dk(  sJ d|d       y)	uZ   파일 내용이 변경되지 않으면 재인덱싱 시 'skipped'를 반환해야 한다.r   r   rA   *   첫 번째 인덱싱 반환값 불일치: skippedu1   재인덱싱(동일 해시) 반환값 불일치: u    (기대: 'skipped')N)r   r   r   rC   r   )r"   r   r3   r#   firstseconds         r   test_TC05_incremental_indexingrL      s    (_,-G *JG,Gs:/EJ0FMMOIU!KE9UUYr"STZS]]q rrr   c                 B   t        | dz        }t        |       }t        |      }|j                  t        |            }|j	                  t
        d       |j                  t        |            }|j                          |dk(  s
J d|       |dk(  sJ d|d	       y
)uP   파일 내용이 변경되면 재인덱싱 시 'updated'를 반환해야 한다.r   r   r	   r
   rA   rH   updatedu-   변경 후 재인덱싱 반환값 불일치: u    (기대: 'updated')N)r   r   r   rC   r   MEMORY_CONTENT_UPDATEDr   )r"   r   r>   r#   rJ   rK   s         r   test_TC06_update_on_changerP      s    (_,-G)HG,Gs8}-E .AH.FMMOIU!KE9UUYn"OPVzYm nnr   c                 r   t        | dz        }t        |       }t        |      }|j                  t        |             |j	                  d      }|j                          t        |t              sJ d       t        |      dkD  sJ d       |d   }dD ]!  }||v rJ d| d	|j                                  y
)uL   한국어 검색어로 FTS5 검색 시 관련 결과를 반환해야 한다.r   r   r;   3   search()가 리스트를 반환하지 않습니다.r   u.   한국어 검색 결과가 비어있습니다.)	file_pathr9   r<   snippetu   결과에 '   ' 키가 없습니다: N)
r   r   r   rC   searchr   r1   listlenkeys)r"   r   r>   r#   resultsrJ   keys          r   test_TC07_fts5_search_koreanr\      s    (_,-G)HG,Gs8}%nn_-GMMOgt$[&[[$w<!MMM AJE8 Ve|U{3%/Fuzz|nUU|Vr   c                    t        | dz        }t        | d      }t        | d      }t        |      }|j	                  t        |             |j	                  t        |             |j                  dd      }|j                  dd	      }|j                          |D ]0  }|j                  d
      dk(  rJ d|j                  d
      d        |D ]0  }|j                  d
      d	k(  rJ d|j                  d
      d        y)uZ   type_filter와 team_filter를 적용하면 조건에 맞는 결과만 반환해야 한다.r   zdiary_test.mdzmem_test.mdr   u   규칙r=   )type_filteru	   메모리diaryr<   u"   type_filter='feedback'인데 type=u   가 반환됨u   type_filter='diary'인데 type=N)r   r   r   r   rC   rV   r   r0   )r"   r   r3   r>   r#   feedback_resultsdiary_resultsrs           r   test_TC08_search_with_filterrc      s   (_,-G !?;J-8HG,Gs:'s8}% ~~hJ~GNN;GNDMMMO  
uuV}
* 	
0v0AO	
*
  
uuV}' 	
-aeeFm->mL	
'
r   c                 ~   t        | dz        }| dz  }|j                          | dz  }|j                          |dz  j                  t        d       |dz  j                  t        d       |dz  j                  t        d       |j                  t        d	t        |             |j                  t        d
t        |             t        |      }|j                         }|j                          t        |t              sJ d       |j                  dd      |j                  dd      z   }|dk\  s
J d|        y)uJ   reindex_all() 호출 시 DIARY_DIR + ANU_MEMORY_DIR를 재인덱싱한다.r   r_   
anu_memory2026-04-05-session-01.mdr	   r
   z2026-04-05-session-02.mddelegation_rules.md	DIARY_DIRANU_MEMORY_DIRr   u3   reindex_all()이 dict를 반환하지 않습니다.rA   r   rN      u=   reindex_all() 후 처리된 파일 수가 3 미만입니다: N)r   mkdirr   r   r   setattrr   reindex_allr   r1   dictr0   )r"   monkeypatchr   	diary_diranu_dirr#   statstotal_processeds           r   test_TC09_reindex_allrt   !  s,   (_,-G 7"IOO%GMMO ++77PW7X++77PW7X$$00'0R{C	NC'7WFG,G!EMMOeT"Y$YY"ii	1-		)Q0GGOa 
GwOr   c                 $   t        | dz        }t        |       }t        |       }t        |      }|j	                  t        |             |j	                  t        |             |j                         }|j                          t        |t              sJ d       d|v sJ d       d|v sJ d       d|v sJ d	       d
|v sJ d       |d   dk\  sJ d|d           t        |d   t              sJ d       t        |d   t              sJ d       y)uL   stats()는 total, by_type, by_team, last_indexed 키를 포함해야 한다.r   r   u-   stats()가 dict를 반환하지 않습니다.totalu'   stats()에 'total' 키가 없습니다.by_typeu)   stats()에 'by_type' 키가 없습니다.by_teamu)   stats()에 'by_team' 키가 없습니다.last_indexedu.   stats()에 'last_indexed' 키가 없습니다.   u   total이 2 미만입니다: u    by_type이 dict가 아닙니다.u    by_team이 dict가 아닙니다.N)	r   r   r   r   rC   rr   r   r1   rn   )r"   r   r3   r>   r#   rD   s         r   test_TC10_statsr{   B  s'   (_,-G *J)HG,Gs:'s8}%]]_FMMOfd#T%TT#fGGGK KKK KKV#U%UU#'?aQ#?w?P!QQfY'.R0RR.fY'.R0RR.r   c                 v   t        | dz        }| dz  }|j                          |dz  j                  t        d       |dz  j                  t        d       |dz  j                  t        d       |dz  j                  d	d       t        |
      }|j                  t        |            }|j                          t        |t              sJ d       dD ]!  }||v rJ d| d|j                                  |d   |d   z   |d   z   |d   z   }|dk(  sJ d| d|        |d   dk(  sJ d|d    d       y)ui   index_directory()는 디렉토리 내 모든 .md 파일을 인덱싱하고 통계를 반환해야 한다.r   md_filesz
file_01.mdr	   r
   z
file_02.mdz
file_03.mdz
ignore.txtu   무시되어야 할 파일r   u7   index_directory()가 dict를 반환하지 않습니다.)rA   rN   rI   errorsu
   stats에 'rU   rA   rN   rI   r~   rj   u-   처리된 파일 수가 3이어야 하는데 u   입니다. stats=u4   신규 인덱싱 파일 수가 3이어야 하는데 u
   입니다.N)r   rk   r   r   r   r   index_directoryr   r1   rn   rY   )r"   r   md_dirr#   rr   r[   rv   s          r   test_TC11_index_directoryr   ]  sw   (_,-G
"F
LLN l&&}w&Gl&&~&Hl&&}w&Gl&&'Cg&VG,G##CK0EMMOeT"]$]]": Ue|Tz#.Eejjl^TT|U )uY//%	2BBU8_TEA: 
7w>OPUwW: q  
>uY?O>PPZ[ r   c                     t        | dz        }t        |      }|j                  d      }|j                          t	        |t
              sJ d       |g k(  s
J d|        y)ua   아무것도 인덱싱하지 않은 빈 DB에서 검색 시 빈 리스트를 반환해야 한다.r   r   u   한국어 검색어rR   u,   빈 DB에서 검색 결과가 있습니다: N)r   r   rV   r   r1   rW   )r"   r   r#   rZ   s       r   test_TC12_search_empty_dbr     sb    (_,-GG,Gnn23GMMOgt$[&[[$b=RH	RR=r   )rf   )rg   )__doc__osr   systextwrappathlibr   pytestpathinsertutils.memory_indexerr   dedentr   r   rO   r   r   r   r%   r7   r?   rF   rL   rP   r\   rc   rt   r{   r   r    r   r   <module>r      s    
  
    ( ) .   ! " ! "  ) 
* 
 t s TX   PT >C2U*I2s$o*V.
JBS6D	Sr   