2017-01-03 10 views
2

필자는 ("FFI 노력"의 일부로) 몇 개의 ExternalStrcture를 구현했으며, 일부는 외부 메모리 교정을 위해 finalization을 구현하려고합니다.Cuis/Squeak/Pharo에서 인스턴스 동작 (테스트 용)을 구현하는 방법은 무엇입니까?

나는 그것에 대한 몇 가지 테스트를 작성하려고하는데, #finalize이 호출되는지를 알기위한 좋은 방법은 테스트를 위해 사용하는 특정 인스턴스의 동작을 변경하는 것입니다. 가능한 경우 테스트를 지원하는 코드로 구현을 오염시키지 않을 것입니다.

특정 방법을 조롱하고 특정 인스턴스 동작을 변경하는 것이 일반적으로 테스트를위한 좋은 도구라고 생각합니다.

나는 다른 방언에서도 가능하다는 것을 알고 있으며, #doesNotUnderstand을 사용하여 Squeak에서 직접 구현했습니다. 그러나 분명히 VM이 지원하는 더 깨끗한 방법이 있는지 알고 싶습니다.

특정 인스턴스가 Cuis/Squeak/Pharo의 특정 메시지에 응답하는 방법을 변경할 수 있습니까?

EllipseMorph 컴파일 복사 :

답변

3

루치아노는이 멋진 예를 준 'DEFAULTCOLOR^붉은 색을'; 새로운 :: openInWorld

메일 스레드가 여기에 있습니다 : 나는 실제로 복원됩니다 (내 경우에는 메모리) 자원을 검증, 테스트 종료 종료 가기로 결정 http://cuis-smalltalk.org/pipermail/cuis-dev_cuis-smalltalk.org/2016-March/000458.html

+0

니스. 그러나 이것은 finalization을 사용하고 @gera는 _testing_ finalization을 위해 필요한 것을 알고 있어야합니다. –

+0

아니요, 파이널 라이즈를 사용하지 않습니다. –

+0

아! 우수한. 나는 그것이 복사 된 클래스를 없애 버릴 줄 알았다. –

2

문제를 처리 한 후 체계. 루시아노 (Luciano)와 후안 (Juan)의 해답 (논평에서)은 매우 흥미 롭긴하지만 인스턴스 동작을 사용하지 않았습니다. 여기에 내가 테스트를 위해 사용하고 코드입니다 :

testFinalizationReleasesExternalMemory 
    " WeakArray restartFinalizationProcess " 
    | handles | 

    handles := (1 to: 11) collect: [:i | 
     Smalltalk garbageCollect. 
     APIStatus create getHandle]. 

    self assert: (handles asSet size) < 11. 

예에서이 #create 포인터 (create 외부 API에서 오는 이름) 메모리를 할당하고 반환하는 외부 함수에 FFI 호출을 사용 :

여기
create 
    | answer | 
    answer := ExternalAPI current createStatus. 
    self finalizationRegistry add: answer. 
    ^answer 

ExternalAPI#createStatusAPIStatus에 대한 메모리를 할당하고 그것의 포인터를 반환하는 API 호출되면, FFI 인터페이스입니다. 마무리에

나는 메모리를 복원 API를 호출 #deleteStatus: 다시 메모리를 해제 API 호출입니다

delete 
    self finalizationRegistry remove: self ifAbsent: []. 
    self library deleteStatus: self. 
    handle := nil. 

.

이 테스트에서는 외부 라이브러리가 사용 가능 해지면 메모리를 재사용한다고 가정합니다. 특히 새로 할당 된 블록의 크기가 이전과 동일 할 경우에만 사용합니다. 이것은 오늘날 대부분의 경우에 맞지만 적어도 뭔가 새로운 것을 배우는 것이 아니라면이 테스트가 실패하는 것을보고 싶습니다.

테스트는 11 개의 외부 구조를 할당하고 포인터를 저장하고 다음 매크로를 할당하기 전에 각 매크로의 메모리를 해제 한 다음 포인터 중 하나가 반복되는지 비교합니다. 나는 왜 10 포인터를 좋은 숫자로 사용하기로 결정했는지 모르겠다. 2는 충분해야하지만, 메모리 할당 알고리즘은 때로는 까다 롭다.

+0

# useFinalization/# ingoreFinalization 등과 같은 단항 메시지 만 보내면되므로 finalizationRegistry에 /에서 인스턴스를 추가/제거하기위한 두 가지 메소드를 Object에 추가 할 것을 제안합니다. –

+0

고마워요! 나는 그것들을 구현했다 :-) – gera