Skip to content

Commit

Permalink
Fix tests
Browse files Browse the repository at this point in the history
Signed-off-by: Paolo Di Tommaso <[email protected]>
  • Loading branch information
pditommaso committed Sep 25, 2024
1 parent ae5aea2 commit dc5535d
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -237,11 +237,11 @@ class ViewController {
}

Map<String, Object> makeScanViewBinding(ScanResult result, Map<String,Object> binding=new HashMap(10)) {
binding.should_refresh = !result.isCompleted()
binding.should_refresh = !result.done()
binding.scan_id = result.id
binding.scan_container_image = result.containerImage ?: '-'
binding.scan_exist = true
binding.scan_completed = result.isCompleted()
binding.scan_completed = result.done()
binding.scan_status = result.status
binding.scan_failed = result.status == ScanResult.FAILED
binding.scan_succeeded = result.status == ScanResult.SUCCEEDED
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class ScanResult implements StateRecord, JobRecord {
}

static ScanResult pending(String scanId, String buildId, String containerImage) {
return new ScanResult(scanId, buildId, containerImage, Instant.now(), null, PENDING, null)
return new ScanResult(scanId, buildId, containerImage, Instant.now(), null, PENDING, List.of())
}

static ScanResult create(String scanId, String buildId, String containerImage, Instant startTime, Duration duration1, String status, List<ScanVulnerability> vulnerabilities){
Expand Down
20 changes: 10 additions & 10 deletions src/test/groovy/io/seqera/wave/controller/ViewControllerTest.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ import io.seqera.wave.service.logs.BuildLogServiceImpl
import io.seqera.wave.service.persistence.PersistenceService
import io.seqera.wave.service.persistence.WaveBuildRecord
import io.seqera.wave.service.persistence.WaveContainerRecord
import io.seqera.wave.service.persistence.WaveScanRecord
import io.seqera.wave.service.scan.ScanResult
import io.seqera.wave.service.scan.ScanVulnerability
import io.seqera.wave.tower.PlatformId
Expand Down Expand Up @@ -306,15 +305,15 @@ class ViewControllerTest extends Specification {
given:
def controller = new ViewController(serverUrl: 'http://foo.com', buildLogService: buildLogService)
and:
def record = new WaveScanRecord(
id: '12345',
buildId: '12345',
containerImage: 'docker.io/some:image',
startTime: Instant.now(),
duration: Duration.ofMinutes(1),
status: ScanResult.SUCCEEDED,
vulnerabilities: [new ScanVulnerability('cve-1', 'HIGH', 'test vul', 'testpkg', '1.0.0', '1.1.0', 'http://vul/cve-1')] )
def result = ScanResult.success(record, record.vulnerabilities)
def result = new ScanResult(
'12345',
'12345',
'docker.io/some:image',
Instant.now(),
Duration.ofMinutes(1),
ScanResult.SUCCEEDED,
[new ScanVulnerability('cve-1', 'HIGH', 'test vul', 'testpkg', '1.0.0', '1.1.0', 'http://vul/cve-1')],
0 )
when:
def binding = controller.makeScanViewBinding(result)
then:
Expand All @@ -323,6 +322,7 @@ class ViewControllerTest extends Specification {
binding.scan_time == formatTimestamp(result.startTime)
binding.scan_duration == formatDuration(result.duration)
binding.scan_succeeded
binding.scan_exitcode == 0
binding.vulnerabilities == [new ScanVulnerability(id:'cve-1', severity:'HIGH', title:'test vul', pkgName:'testpkg', installedVersion:'1.0.0', fixedVersion:'1.1.0', primaryUrl:'http://vul/cve-1')]
binding.build_url == 'http://foo.com/view/builds/12345'
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,12 @@
package io.seqera.wave.service.persistence

import spock.lang.Specification
import spock.lang.Unroll

import java.time.Duration
import java.time.Instant

import io.seqera.wave.service.scan.ScanResult
import io.seqera.wave.service.scan.ScanVulnerability

/**
*
* @author Munish Chouhan <[email protected]>
Expand Down Expand Up @@ -65,6 +63,7 @@ class WaveScanRecordTest extends Specification {
scanResult.containerImage == containerImage
scanResult.isCompleted()
scanResult.isSucceeded()
scanResult.done()

when:
def scanRecord = new WaveScanRecord(scanId, scanResult)
Expand All @@ -75,14 +74,4 @@ class WaveScanRecordTest extends Specification {
scanRecord.vulnerabilities[0] == scanVulnerability
}

@Unroll
def 'should validate done' () {
expect:
RECORD.done() == EXPECTED

where:
EXPECTED| RECORD
false | new WaveScanRecord('123', 'scan-123', 'testcontainerimage', Instant.now())
true | new WaveScanRecord('123', 'scan-123', 'testcontainerimage', Instant.now(), Duration.ofMinutes(1), 'OK', [])
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import io.seqera.wave.service.job.JobService
import io.seqera.wave.service.job.JobSpec
import io.seqera.wave.service.job.JobState
import io.seqera.wave.service.persistence.PersistenceService
import io.seqera.wave.service.persistence.WaveScanRecord
import jakarta.inject.Inject
/**
* Tests for ContainerScanServiceImpl
Expand All @@ -45,6 +44,8 @@ class ContainerScanServiceImplTest extends Specification {

@Inject PersistenceService persistenceService

@Inject ScanStateStore stateStore

def 'should start scan successfully'() {
given:
def workDir = Files.createTempDirectory('test')
Expand Down Expand Up @@ -125,59 +126,117 @@ class ContainerScanServiceImplTest extends Specification {
def workDir = Files.createTempDirectory('test')
def reportFile = workDir.resolve('report.json')
Files.write(reportFile, trivyDockerResulJson.bytes)
def mockPersistenceService = Mock(PersistenceService)
and:
def KEY = 'scan-10'
def jobService = Mock(JobService)
def service = new ContainerScanServiceImpl(persistenceService: mockPersistenceService, jobService: jobService)
def job = JobSpec.scan('scan-1', 'ubuntu:latest', Instant.now(), Duration.ofMinutes(1), workDir)
def state = Mock(JobState)
def scan = new WaveScanRecord('scan-1', 'build-1', 'ubuntu:latest', Instant.now())
def service = new ContainerScanServiceImpl(scanStore: stateStore, persistenceService: persistenceService, jobService: jobService)
def job = JobSpec.scan(KEY, 'ubuntu:latest', Instant.now(), Duration.ofMinutes(1), workDir)
def scan = new ScanResult(KEY, 'build-1', 'ubuntu:latest', Instant.now())

when:
service.onJobCompletion(job, scan, state)
service.onJobCompletion(job, scan, new JobState(JobState.Status.SUCCEEDED,0))
then:
1 * state.completed() >> true
1 * mockPersistenceService.updateScanRecord(_ as WaveScanRecord) >> { WaveScanRecord scanRecord -> assert scanRecord.status=='SUCCEEDED' }
with( stateStore.getScan(KEY)) {
id == KEY
buildId == 'build-1'
containerImage == 'ubuntu:latest'
status == 'SUCCEEDED'
exitCode == 0
}
and:
with( persistenceService.loadScanRecord(KEY) ) {
id == KEY
buildId == 'build-1'
containerImage == 'ubuntu:latest'
status == 'SUCCEEDED'
}

when:
service.onJobCompletion(job, scan, state)
service.onJobCompletion(job, scan, new JobState(JobState.Status.FAILED, 10, "I'm broken"))
then:
1 * state.completed() >> false
1 * mockPersistenceService.updateScanRecord(_ as WaveScanRecord) >> { WaveScanRecord scanRecord -> assert scanRecord.status=='FAILED' }
with( stateStore.getScan(KEY) ) {
id == KEY
buildId == 'build-1'
containerImage == 'ubuntu:latest'
status == 'FAILED'
exitCode == 10
logs == "I'm broken"
}
and:
with( persistenceService.loadScanRecord(KEY) ) {
id == KEY
buildId == 'build-1'
containerImage == 'ubuntu:latest'
status == 'FAILED'
}

cleanup:
workDir?.deleteDir()
stateStore.clear()
}

def 'should handle job error event and update scan record'() {
given:
def mockPersistenceService = Mock(PersistenceService)
def KEY = 'scan-20'
def jobService = Mock(JobService)
def service = new ContainerScanServiceImpl(persistenceService: mockPersistenceService, jobService: jobService)
def job = JobSpec.scan('scan-1', 'ubuntu:latest', Instant.now(), Duration.ofMinutes(1), Path.of('/work/dir'))
def error = new Exception('error')
def scan = new WaveScanRecord('scan-1', 'build-1', 'ubuntu:latest', Instant.now())
def service = new ContainerScanServiceImpl(scanStore: stateStore, persistenceService: persistenceService, jobService: jobService)
def job = JobSpec.scan(KEY, 'ubuntu:latest', Instant.now(), Duration.ofMinutes(1), Path.of('/work/dir'))
def error = new Exception('Some error msg')
def scan = new ScanResult(KEY, 'build-20', 'ubuntu:latest', Instant.now())

when:
service.onJobException(job, scan, error)
then:
1 * mockPersistenceService.updateScanRecord(_ as WaveScanRecord) >> { WaveScanRecord scanRecord -> assert scanRecord.status=='FAILED' }
with( stateStore.getScan(KEY) ) {
id == KEY
buildId == 'build-20'
containerImage == 'ubuntu:latest'
status == 'FAILED'
exitCode == null
logs == "Some error msg"
}
and:
with( persistenceService.loadScanRecord(KEY) ) {
id == KEY
buildId == 'build-20'
containerImage == 'ubuntu:latest'
status == 'FAILED'
}

cleanup:
stateStore.clear()
}

def 'should handle job timeout event and update scan record'() {
given:
def mockPersistenceService = Mock(PersistenceService)
def KEY = 'scan-30'
def jobService = Mock(JobService)
def service = new ContainerScanServiceImpl(persistenceService: mockPersistenceService, jobService: jobService)
def job = JobSpec.scan('scan-1', 'ubuntu:latest', Instant.now(), Duration.ofMinutes(1), Path.of('/work/dir'))
def scan = new WaveScanRecord('scan-1', 'build-1', 'ubuntu:latest', Instant.now())
def service = new ContainerScanServiceImpl(scanStore: stateStore, persistenceService: persistenceService, jobService: jobService)
def job = JobSpec.scan(KEY, 'ubuntu:latest', Instant.now(), Duration.ofMinutes(1), Path.of('/work/dir'))
def scan = new ScanResult(KEY, 'build-30', 'ubuntu:latest', Instant.now())

when:
service.onJobTimeout(job, scan)

then:
1 * mockPersistenceService.updateScanRecord(_ as WaveScanRecord) >> { WaveScanRecord scanRecord -> assert scanRecord.status=='FAILED' }
with( stateStore.getScan(KEY) ) {
id == KEY
buildId == 'build-30'
containerImage == 'ubuntu:latest'
status == 'FAILED'
exitCode == null
logs == "Container scan timed out"
}
and:
with( persistenceService.loadScanRecord(KEY) ) {
id == KEY
buildId == 'build-30'
containerImage == 'ubuntu:latest'
status == 'FAILED'
}

cleanup:
stateStore.clear()
}

}
58 changes: 38 additions & 20 deletions src/test/groovy/io/seqera/wave/service/scan/ScanResultTest.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ import java.time.Duration
import java.time.Instant

import io.seqera.wave.core.ContainerPlatform
import io.seqera.wave.service.persistence.WaveScanRecord

/**
*
* @author Paolo Di Tommaso <[email protected]>
Expand Down Expand Up @@ -78,6 +76,7 @@ class ScanResultTest extends Specification {
)
then:
result.isCompleted() == EXPECTED
result.done() == EXPECTED

where:
DURATION | EXPECTED
Expand Down Expand Up @@ -129,16 +128,16 @@ class ScanResultTest extends Specification {
def elapsed = Duration.ofMinutes(1)
def ts = Instant.now().minus(elapsed)
and:
def record = new WaveScanRecord(
id: '12345',
buildId: 'build-12345',
containerImage: 'docker.io/some:image',
startTime: ts,
duration: elapsed,
status: ScanResult.SUCCEEDED,
vulnerabilities: [cve1] )
def scan = new ScanResult(
'12345',
'build-12345',
'docker.io/some:image',
ts,
elapsed,
ScanResult.SUCCEEDED,
[cve1] )
when:
def result = ScanResult.success(record, record.vulnerabilities)
def result = scan.success(scan.vulnerabilities)
then:
result.id == '12345'
result.buildId == 'build-12345'
Expand All @@ -154,16 +153,16 @@ class ScanResultTest extends Specification {
def elapsed = Duration.ofMinutes(1)
def ts = Instant.now().minus(elapsed)
and:
def record = new WaveScanRecord(
id: '12345',
buildId: 'build-12345',
containerImage: 'docker.io/some:image',
startTime: ts,
duration: elapsed,
status: ScanResult.FAILED,
vulnerabilities: [] )
def scan = new ScanResult(
'12345',
'build-12345',
'docker.io/some:image',
ts,
elapsed,
ScanResult.FAILED,
[] )
when:
def result = ScanResult.failure(record)
def result = scan.failure(1, "Oops something has failed")
then:
result.id == '12345'
result.buildId == 'build-12345'
Expand All @@ -172,6 +171,8 @@ class ScanResultTest extends Specification {
nearly(result.duration, elapsed)
result.status == ScanResult.FAILED
result.vulnerabilities == []
result.exitCode == 1
result.logs == "Oops something has failed"
}

def 'should create failed result from request' () {
Expand All @@ -198,4 +199,21 @@ class ScanResultTest extends Specification {
result.status == ScanResult.FAILED
result.vulnerabilities == []
}

def 'should create scan pending' () {
given:
def ts = Instant.now()

when:
def scan = ScanResult.pending('result-123', 'build-345', 'docker.io/foo/bar')
then:
scan.id == 'result-123'
scan.buildId == 'build-345'
scan.containerImage == 'docker.io/foo/bar'
scan.startTime >= ts
scan.status == ScanResult.PENDING
scan.vulnerabilities == []
scan.exitCode == null
scan.logs == null
}
}

0 comments on commit dc5535d

Please sign in to comment.