0565938956
This change pulls as much pagination logic out of the database implementation as possible. Database implementations should now be able to marshal whatever state they need into opaque tokens with the utilities in the pagination package.
251 lines
7.3 KiB
Go
251 lines
7.3 KiB
Go
// Copyright 2018 clair authors
|
|
//
|
|
// 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.
|
|
|
|
package pgsql
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/coreos/clair/database"
|
|
)
|
|
|
|
func TestPagination(t *testing.T) {
|
|
datastore, tx := openSessionForTest(t, "Pagination", true)
|
|
defer closeTest(t, datastore, tx)
|
|
|
|
ns := database.Namespace{
|
|
Name: "debian:7",
|
|
VersionFormat: "dpkg",
|
|
}
|
|
|
|
vNew := database.Vulnerability{
|
|
Namespace: ns,
|
|
Name: "CVE-OPENSSL-1-DEB7",
|
|
Description: "A vulnerability affecting OpenSSL < 2.0 on Debian 7.0",
|
|
Link: "http://google.com/#q=CVE-OPENSSL-1-DEB7",
|
|
Severity: database.HighSeverity,
|
|
}
|
|
|
|
vOld := database.Vulnerability{
|
|
Namespace: ns,
|
|
Name: "CVE-NOPE",
|
|
Description: "A vulnerability affecting nothing",
|
|
Severity: database.UnknownSeverity,
|
|
}
|
|
|
|
noti, ok, err := tx.FindVulnerabilityNotification("test", 1, "", "")
|
|
oldPage := database.PagedVulnerableAncestries{
|
|
Vulnerability: vOld,
|
|
Limit: 1,
|
|
Affected: make(map[int]string),
|
|
End: true,
|
|
}
|
|
|
|
newPage1 := database.PagedVulnerableAncestries{
|
|
Vulnerability: vNew,
|
|
Limit: 1,
|
|
Affected: map[int]string{3: "ancestry-3"},
|
|
End: false,
|
|
}
|
|
|
|
newPage2 := database.PagedVulnerableAncestries{
|
|
Vulnerability: vNew,
|
|
Limit: 1,
|
|
Affected: map[int]string{4: "ancestry-4"},
|
|
Next: "",
|
|
End: true,
|
|
}
|
|
|
|
if assert.Nil(t, err) && assert.True(t, ok) {
|
|
assert.Equal(t, "test", noti.Name)
|
|
if assert.NotNil(t, noti.Old) && assert.NotNil(t, noti.New) {
|
|
var oldPage Page
|
|
err := tx.key.UnmarshalToken(noti.Old.Current, &oldPage)
|
|
if !assert.Nil(t, err) {
|
|
assert.FailNow(t, "")
|
|
}
|
|
|
|
assert.Equal(t, int64(0), oldPage.StartID)
|
|
var newPage Page
|
|
err = tx.key.UnmarshalToken(noti.New.Current, &newPage)
|
|
if !assert.Nil(t, err) {
|
|
assert.FailNow(t, "")
|
|
}
|
|
var newPageNext Page
|
|
err = tx.key.UnmarshalToken(noti.New.Next, &newPageNext)
|
|
if !assert.Nil(t, err) {
|
|
assert.FailNow(t, "")
|
|
}
|
|
assert.Equal(t, int64(0), newPage.StartID)
|
|
assert.Equal(t, int64(4), newPageNext.StartID)
|
|
|
|
noti.Old.Current = ""
|
|
noti.New.Current = ""
|
|
noti.New.Next = ""
|
|
assert.Equal(t, oldPage, *noti.Old)
|
|
assert.Equal(t, newPage1, *noti.New)
|
|
}
|
|
}
|
|
|
|
pageNum1, err := tx.key.MarshalToken(Page{0})
|
|
if !assert.Nil(t, err) {
|
|
assert.FailNow(t, "")
|
|
}
|
|
|
|
pageNum2, err := tx.key.MarshalToken(Page{4})
|
|
if !assert.Nil(t, err) {
|
|
assert.FailNow(t, "")
|
|
}
|
|
|
|
noti, ok, err = tx.FindVulnerabilityNotification("test", 1, pageNum1, pageNum2)
|
|
if assert.Nil(t, err) && assert.True(t, ok) {
|
|
assert.Equal(t, "test", noti.Name)
|
|
if assert.NotNil(t, noti.Old) && assert.NotNil(t, noti.New) {
|
|
var oldCurrentPage Page
|
|
err = tx.key.UnmarshalToken(noti.Old.Current, &oldCurrentPage)
|
|
if !assert.Nil(t, err) {
|
|
assert.FailNow(t, "")
|
|
}
|
|
|
|
var newCurrentPage Page
|
|
err = tx.key.UnmarshalToken(noti.New.Current, &newCurrentPage)
|
|
if !assert.Nil(t, err) {
|
|
assert.FailNow(t, "")
|
|
}
|
|
|
|
assert.Equal(t, int64(0), oldCurrentPage.StartID)
|
|
assert.Equal(t, int64(4), newCurrentPage.StartID)
|
|
noti.Old.Current = ""
|
|
noti.New.Current = ""
|
|
assert.Equal(t, oldPage, *noti.Old)
|
|
assert.Equal(t, newPage2, *noti.New)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestInsertVulnerabilityNotifications(t *testing.T) {
|
|
datastore, tx := openSessionForTest(t, "InsertVulnerabilityNotifications", true)
|
|
|
|
n1 := database.VulnerabilityNotification{}
|
|
n3 := database.VulnerabilityNotification{
|
|
NotificationHook: database.NotificationHook{
|
|
Name: "random name",
|
|
Created: time.Now(),
|
|
},
|
|
Old: nil,
|
|
New: &database.Vulnerability{},
|
|
}
|
|
n4 := database.VulnerabilityNotification{
|
|
NotificationHook: database.NotificationHook{
|
|
Name: "random name",
|
|
Created: time.Now(),
|
|
},
|
|
Old: nil,
|
|
New: &database.Vulnerability{
|
|
Name: "CVE-OPENSSL-1-DEB7",
|
|
Namespace: database.Namespace{
|
|
Name: "debian:7",
|
|
VersionFormat: "dpkg",
|
|
},
|
|
},
|
|
}
|
|
|
|
// invalid case
|
|
err := tx.InsertVulnerabilityNotifications([]database.VulnerabilityNotification{n1})
|
|
assert.NotNil(t, err)
|
|
|
|
// invalid case: unknown vulnerability
|
|
err = tx.InsertVulnerabilityNotifications([]database.VulnerabilityNotification{n3})
|
|
assert.NotNil(t, err)
|
|
|
|
// invalid case: duplicated input notification
|
|
err = tx.InsertVulnerabilityNotifications([]database.VulnerabilityNotification{n4, n4})
|
|
assert.NotNil(t, err)
|
|
tx = restartSession(t, datastore, tx, false)
|
|
|
|
// valid case
|
|
err = tx.InsertVulnerabilityNotifications([]database.VulnerabilityNotification{n4})
|
|
assert.Nil(t, err)
|
|
// invalid case: notification is already in database
|
|
err = tx.InsertVulnerabilityNotifications([]database.VulnerabilityNotification{n4})
|
|
assert.NotNil(t, err)
|
|
|
|
closeTest(t, datastore, tx)
|
|
}
|
|
|
|
func TestFindNewNotification(t *testing.T) {
|
|
datastore, tx := openSessionForTest(t, "FindNewNotification", true)
|
|
defer closeTest(t, datastore, tx)
|
|
|
|
noti, ok, err := tx.FindNewNotification(time.Now())
|
|
if assert.Nil(t, err) && assert.True(t, ok) {
|
|
assert.Equal(t, "test", noti.Name)
|
|
assert.Equal(t, time.Time{}, noti.Notified)
|
|
assert.Equal(t, time.Time{}, noti.Created)
|
|
assert.Equal(t, time.Time{}, noti.Deleted)
|
|
}
|
|
|
|
// can't find the notified
|
|
assert.Nil(t, tx.MarkNotificationNotified("test"))
|
|
// if the notified time is before
|
|
noti, ok, err = tx.FindNewNotification(time.Now().Add(-time.Duration(10 * time.Second)))
|
|
assert.Nil(t, err)
|
|
assert.False(t, ok)
|
|
// can find the notified after a period of time
|
|
noti, ok, err = tx.FindNewNotification(time.Now().Add(time.Duration(1000)))
|
|
if assert.Nil(t, err) && assert.True(t, ok) {
|
|
assert.Equal(t, "test", noti.Name)
|
|
assert.NotEqual(t, time.Time{}, noti.Notified)
|
|
assert.Equal(t, time.Time{}, noti.Created)
|
|
assert.Equal(t, time.Time{}, noti.Deleted)
|
|
}
|
|
|
|
assert.Nil(t, tx.DeleteNotification("test"))
|
|
// can't find in any time
|
|
noti, ok, err = tx.FindNewNotification(time.Now().Add(-time.Duration(1000)))
|
|
assert.Nil(t, err)
|
|
assert.False(t, ok)
|
|
|
|
noti, ok, err = tx.FindNewNotification(time.Now().Add(time.Duration(1000)))
|
|
assert.Nil(t, err)
|
|
assert.False(t, ok)
|
|
}
|
|
|
|
func TestMarkNotificationNotified(t *testing.T) {
|
|
datastore, tx := openSessionForTest(t, "MarkNotificationNotified", true)
|
|
defer closeTest(t, datastore, tx)
|
|
|
|
// invalid case: notification doesn't exist
|
|
assert.NotNil(t, tx.MarkNotificationNotified("non-existing"))
|
|
// valid case
|
|
assert.Nil(t, tx.MarkNotificationNotified("test"))
|
|
// valid case
|
|
assert.Nil(t, tx.MarkNotificationNotified("test"))
|
|
}
|
|
|
|
func TestDeleteNotification(t *testing.T) {
|
|
datastore, tx := openSessionForTest(t, "DeleteNotification", true)
|
|
defer closeTest(t, datastore, tx)
|
|
|
|
// invalid case: notification doesn't exist
|
|
assert.NotNil(t, tx.DeleteNotification("non-existing"))
|
|
// valid case
|
|
assert.Nil(t, tx.DeleteNotification("test"))
|
|
// invalid case: notification is already deleted
|
|
assert.NotNil(t, tx.DeleteNotification("test"))
|
|
}
|