2017-01-15 15:52:13 +00:00
|
|
|
// Copyright 2017 clair authors
|
2016-01-19 20:16:45 +00:00
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2016-01-18 23:52:16 +00:00
|
|
|
package pgsql
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"math/rand"
|
|
|
|
"runtime"
|
|
|
|
"strconv"
|
|
|
|
"sync"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2016-05-02 22:33:03 +00:00
|
|
|
"github.com/pborman/uuid"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
|
2017-01-15 15:52:13 +00:00
|
|
|
"github.com/coreos/clair"
|
2016-01-18 23:52:16 +00:00
|
|
|
"github.com/coreos/clair/database"
|
2017-01-03 21:00:20 +00:00
|
|
|
"github.com/coreos/clair/ext/versionfmt/dpkg"
|
2016-01-18 23:52:16 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
numVulnerabilities = 100
|
|
|
|
numFeatureVersions = 100
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestRaceAffects(t *testing.T) {
|
2016-05-02 22:33:03 +00:00
|
|
|
datastore, err := openDatabaseForTest("RaceAffects", false)
|
2016-01-18 23:52:16 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
defer datastore.Close()
|
|
|
|
|
|
|
|
// Insert the Feature on which we'll work.
|
|
|
|
feature := database.Feature{
|
2016-12-28 01:45:11 +00:00
|
|
|
Namespace: database.Namespace{
|
|
|
|
Name: "TestRaceAffectsFeatureNamespace1",
|
2017-01-03 21:00:20 +00:00
|
|
|
VersionFormat: dpkg.ParserName,
|
2016-12-28 01:45:11 +00:00
|
|
|
},
|
|
|
|
Name: "TestRaceAffecturesFeature1",
|
2016-01-18 23:52:16 +00:00
|
|
|
}
|
|
|
|
_, err = datastore.insertFeature(feature)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize random generator and enforce max procs.
|
|
|
|
rand.Seed(time.Now().UnixNano())
|
|
|
|
runtime.GOMAXPROCS(runtime.NumCPU())
|
|
|
|
|
|
|
|
// Generate FeatureVersions.
|
|
|
|
featureVersions := make([]database.FeatureVersion, numFeatureVersions)
|
|
|
|
for i := 0; i < numFeatureVersions; i++ {
|
|
|
|
version := rand.Intn(numFeatureVersions)
|
|
|
|
|
|
|
|
featureVersions[i] = database.FeatureVersion{
|
|
|
|
Feature: feature,
|
2016-12-28 01:45:11 +00:00
|
|
|
Version: strconv.Itoa(version),
|
2016-01-18 23:52:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generate vulnerabilities.
|
|
|
|
// They are mapped by fixed version, which will make verification really easy afterwards.
|
|
|
|
vulnerabilities := make(map[int][]database.Vulnerability)
|
|
|
|
for i := 0; i < numVulnerabilities; i++ {
|
|
|
|
version := rand.Intn(numFeatureVersions) + 1
|
|
|
|
|
|
|
|
// if _, ok := vulnerabilities[version]; !ok {
|
|
|
|
// vulnerabilities[version] = make([]database.Vulnerability)
|
|
|
|
// }
|
|
|
|
|
|
|
|
vulnerability := database.Vulnerability{
|
|
|
|
Name: uuid.New(),
|
|
|
|
Namespace: feature.Namespace,
|
|
|
|
FixedIn: []database.FeatureVersion{
|
2016-02-25 00:29:36 +00:00
|
|
|
{
|
2016-01-18 23:52:16 +00:00
|
|
|
Feature: feature,
|
2016-12-28 01:45:11 +00:00
|
|
|
Version: strconv.Itoa(version),
|
2016-01-18 23:52:16 +00:00
|
|
|
},
|
|
|
|
},
|
2017-01-15 15:52:13 +00:00
|
|
|
Severity: clair.Unknown,
|
2016-01-18 23:52:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
vulnerabilities[version] = append(vulnerabilities[version], vulnerability)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Insert featureversions and vulnerabilities in parallel.
|
|
|
|
var wg sync.WaitGroup
|
|
|
|
wg.Add(2)
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
defer wg.Done()
|
|
|
|
for _, vulnerabilitiesM := range vulnerabilities {
|
|
|
|
for _, vulnerability := range vulnerabilitiesM {
|
2016-02-04 22:10:19 +00:00
|
|
|
err = datastore.InsertVulnerabilities([]database.Vulnerability{vulnerability}, true)
|
2016-01-18 23:52:16 +00:00
|
|
|
assert.Nil(t, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fmt.Println("finished to insert vulnerabilities")
|
|
|
|
}()
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
defer wg.Done()
|
|
|
|
for i := 0; i < len(featureVersions); i++ {
|
|
|
|
featureVersions[i].ID, err = datastore.insertFeatureVersion(featureVersions[i])
|
|
|
|
assert.Nil(t, err)
|
|
|
|
}
|
|
|
|
fmt.Println("finished to insert featureVersions")
|
|
|
|
}()
|
|
|
|
|
|
|
|
wg.Wait()
|
|
|
|
|
|
|
|
// Verify consistency now.
|
|
|
|
var actualAffectedNames []string
|
|
|
|
var expectedAffectedNames []string
|
|
|
|
|
|
|
|
for _, featureVersion := range featureVersions {
|
2016-12-28 01:45:11 +00:00
|
|
|
featureVersionVersion, _ := strconv.Atoi(featureVersion.Version)
|
2016-01-18 23:52:16 +00:00
|
|
|
|
|
|
|
// Get actual affects.
|
2016-02-23 00:15:38 +00:00
|
|
|
rows, err := datastore.Query(searchComplexTestFeatureVersionAffects,
|
2016-01-18 23:52:16 +00:00
|
|
|
featureVersion.ID)
|
|
|
|
assert.Nil(t, err)
|
|
|
|
defer rows.Close()
|
|
|
|
|
|
|
|
var vulnName string
|
|
|
|
for rows.Next() {
|
|
|
|
err = rows.Scan(&vulnName)
|
|
|
|
if !assert.Nil(t, err) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
actualAffectedNames = append(actualAffectedNames, vulnName)
|
|
|
|
}
|
|
|
|
if assert.Nil(t, rows.Err()) {
|
|
|
|
rows.Close()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get expected affects.
|
|
|
|
for i := numVulnerabilities; i > featureVersionVersion; i-- {
|
|
|
|
for _, vulnerability := range vulnerabilities[i] {
|
|
|
|
expectedAffectedNames = append(expectedAffectedNames, vulnerability.Name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-18 02:40:59 +00:00
|
|
|
assert.Len(t, compareStringLists(expectedAffectedNames, actualAffectedNames), 0)
|
|
|
|
assert.Len(t, compareStringLists(actualAffectedNames, expectedAffectedNames), 0)
|
2016-01-18 23:52:16 +00:00
|
|
|
}
|
|
|
|
}
|