89 in run in that new VM" |
89 in run in that new VM" |
90 |
90 |
91 | tempDir testcaseFile exe args script environment outputFile output pid blocker status spawn | |
91 | tempDir testcaseFile exe args script environment outputFile output pid blocker status spawn | |
92 |
92 |
93 spawn := (self class lookupMethodFor: testSelector) annotationAt: #spawn:. |
93 spawn := (self class lookupMethodFor: testSelector) annotationAt: #spawn:. |
94 spawn isNil ifTrue:[ |
94 spawn isNil ifTrue:[ |
95 self error: 'No <spawn:> annotation'. |
95 self error: 'No <spawn:> annotation'. |
96 ]. |
96 ]. |
97 (spawn argumentAt: 1) == false ifTrue:[ |
97 (spawn argumentAt: 1) == false ifTrue:[ |
98 ^ super runCase. |
98 ^ super runCase. |
99 ] ifFalse:[ |
99 ] ifFalse:[ |
100 (spawn argumentAt: 1) ~~ true ifTrue:[ |
100 (spawn argumentAt: 1) ~~ true ifTrue:[ |
101 self error: 'Argument to <spawn:> must be either `true` or `false`'. |
101 self error: 'Argument to <spawn:> must be either `true` or `false`'. |
102 ] |
102 ] |
103 ]. |
103 ]. |
104 |
104 |
105 [ |
105 [ |
106 tempDir := Filename newTemporary. |
106 tempDir := Filename newTemporary. |
107 tempDir makeDirectory. |
107 tempDir makeDirectory. |
108 testcaseFile := tempDir / ((Smalltalk fileNameForClass: self class) , '.st'). |
108 testcaseFile := tempDir / ((Smalltalk fileNameForClass: self class) , '.st'). |
109 self class fileOutAs: testcaseFile. |
109 self class fileOutAs: testcaseFile. |
110 |
110 |
111 script := 'Smalltalk packagePath: %1. |
111 script := 'Smalltalk packagePath: %1. |
112 Smalltalk loadPackage:%2. |
112 Smalltalk loadPackage:%2. |
113 Smalltalk fileIn: %3. |
113 Smalltalk fileIn: %3. |
114 (%4 selector: %5) runCaseInternal.' |
114 (%4 selector: %5) runCaseInternal.' |
115 bindWith: Smalltalk packagePath asArray storeString |
115 bindWith: Smalltalk packagePath asArray storeString |
116 with: self class package storeString |
116 with: self class package storeString |
117 with: testcaseFile pathName storeString |
117 with: testcaseFile pathName storeString |
118 with: self class name |
118 with: self class name |
119 with: testSelector storeString. |
119 with: testSelector storeString. |
120 |
120 |
121 exe := OperatingSystem pathOfSTXExecutable. |
121 exe := OperatingSystem pathOfSTXExecutable. |
122 args := { exe . '--abortOnSEGV' . '--execute' . ( tempDir / 'run.st' ) pathName }. |
122 args := { exe . '--abortOnSEGV' . '--execute' . ( tempDir / 'run.st' ) pathName }. |
123 |
123 |
124 OperatingSystem isMSWINDOWSlike ifTrue:[ |
124 OperatingSystem isMSWINDOWSlike ifTrue:[ |
125 args := String streamContents:[:s| |
125 args := String streamContents:[:s| |
126 args |
126 args |
127 do:[:each | s nextPut:$"; nextPutAll: each; nextPut: $"] |
127 do:[:each | s nextPut:$"; nextPutAll: each; nextPut: $"] |
128 separatedBy: [ s space ] |
128 separatedBy: [ s space ] |
129 ] |
129 ] |
130 ]. |
130 ]. |
131 |
131 |
132 outputFile := tempDir / 'output.txt'. |
132 outputFile := tempDir / 'output.txt'. |
133 output := outputFile writeStream. |
133 output := outputFile writeStream. |
134 |
134 |
135 "/ Now, spit out some helper files that for debugging. |
135 "/ Now, spit out some helper files that for debugging. |
136 ( tempDir / 'run.st' ) writingFileDo:[ :f | |
136 ( tempDir / 'run.st' ) writingFileDo:[ :f | |
137 f nextPutAll: script. |
137 f nextPutAll: script. |
138 ]. |
138 ]. |
139 environment := OperatingSystem isUNIXlike |
139 environment := OperatingSystem isUNIXlike |
140 ifTrue:[OperatingSystem getEnvironment copy] |
140 ifTrue:[OperatingSystem getEnvironment copy] |
141 ifFalse:[environment := Dictionary new]. |
141 ifFalse:[environment := Dictionary new]. |
142 blocker := Semaphore new. |
142 blocker := Semaphore new. |
143 |
143 |
144 Processor monitor:[ |
144 Processor monitor:[ |
145 pid := OperatingSystem exec: exe withArguments:args |
145 pid := OperatingSystem exec: exe withArguments:args |
146 environment:environment |
146 environment:environment |
147 fileDescriptors:{0 . output fileDescriptor . output fileDescriptor } |
147 fileDescriptors:{0 . output fileDescriptor . output fileDescriptor } |
148 fork:true |
148 fork:true |
149 newPgrp:false |
149 newPgrp:false |
150 inDirectory: Filename currentDirectory pathName |
150 inDirectory: Filename currentDirectory pathName |
151 ] action: [ :s | |
151 ] action: [ :s | |
152 status := s. |
152 status := s. |
153 blocker signal. |
153 blocker signal. |
154 ]. |
154 ]. |
155 |
155 |
156 output close. |
156 output close. |
157 |
157 |
158 pid isNil ifTrue:[ |
158 pid isNil ifTrue:[ |
159 self error: 'Failed to spawn test'. |
159 self error: 'Failed to spawn test'. |
160 ^ self. |
160 ^ self. |
161 ]. |
161 ]. |
162 |
162 |
163 blocker wait. |
163 blocker wait. |
164 |
164 |
165 status code == EXIT_CODE_FAILURE ifTrue:[ |
165 status code == EXIT_CODE_FAILURE ifTrue:[ |
166 (outputFile notNil and:[ outputFile exists ]) ifTrue:[ |
166 (outputFile notNil and:[ outputFile exists ]) ifTrue:[ |
167 Stdout nextPutAll: '== TEST FAILED: '; nextPutAll: testSelector; nextPutLine:' =='. |
167 Stdout nextPutAll: '== TEST FAILED: '; nextPutAll: testSelector; nextPutLine:' =='. |
168 outputFile readingFileDo:[:s| |
168 outputFile readingFileDo:[:s| |
169 [ s atEnd ] whileFalse:[ |
169 [ s atEnd ] whileFalse:[ |
170 Stdout nextPutLine: s nextLine. |
170 Stdout nextPutLine: s nextLine. |
171 ]. |
171 ]. |
172 ]. |
172 ]. |
173 ]. |
173 ]. |
174 self assert: false description: 'Assertion failed, see log'. |
174 self assert: false description: 'Assertion failed, see log'. |
175 ]. |
175 ]. |
176 (status code == EXIT_CODE_ERROR or:[status status == #signal]) ifTrue:[ |
176 (status code == EXIT_CODE_ERROR or:[status status == #signal]) ifTrue:[ |
177 (outputFile notNil and:[ outputFile exists ]) ifTrue:[ |
177 (outputFile notNil and:[ outputFile exists ]) ifTrue:[ |
178 Stdout nextPutAll: '== TEST ERROR: '; nextPutAll: testSelector; nextPutLine:' =='. |
178 Stdout nextPutAll: '== TEST ERROR: '; nextPutAll: testSelector; nextPutLine:' =='. |
179 outputFile readingFileDo:[:s| |
179 outputFile readingFileDo:[:s| |
180 [ s atEnd ] whileFalse:[ |
180 [ s atEnd ] whileFalse:[ |
181 Stdout nextPutLine: s nextLine. |
181 Stdout nextPutLine: s nextLine. |
182 ]. |
182 ]. |
183 ]. |
183 ]. |
184 ]. |
184 ]. |
185 self error: 'Error occured'. |
185 self error: 'Error occured'. |
186 ]. |
186 ]. |
187 ] ensure:[ |
187 ] ensure:[ |
188 (tempDir notNil and:[tempDir exists]) ifTrue:[ |
188 (tempDir notNil and:[tempDir exists]) ifTrue:[ |
189 [ |
189 [ |
190 tempDir recursiveRemove. |
190 tempDir recursiveRemove. |
191 ] on: Error do:[:ex | |
191 ] on: Error do:[:ex | |
192 OperatingSystem isMSWINDOWSlike ifFalse:[ |
192 OperatingSystem isMSWINDOWSlike ifFalse:[ |
193 ex reject. |
193 ex reject. |
194 ]. |
194 ]. |
195 ] |
195 ] |
196 ]. |
196 ]. |
197 ]. |
197 ]. |
198 |
198 |
199 " |
199 " |
200 VMCrashTestCase run:#test_infrastructure |
200 VMCrashTestCase run:#test_infrastructure |
201 " |
201 " |