mirror of
https://github.com/token2/snapd.git
synced 2026-03-13 11:15:47 -07:00
This commit replaces the use of "sanity" with more inclusive naming. When `sanity` is used in a more general sense either `validity` or `quick` is used.
559 lines
18 KiB
Go
559 lines
18 KiB
Go
// -*- Mode: Go; indent-tabs-mode: t -*-
|
|
|
|
/*
|
|
* Copyright (C) 2017 Canonical Ltd
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 3 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
package errtracker_test
|
|
|
|
import (
|
|
"crypto/sha512"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
. "gopkg.in/check.v1"
|
|
"gopkg.in/mgo.v2/bson"
|
|
|
|
"github.com/snapcore/snapd/arch"
|
|
"github.com/snapcore/snapd/dirs"
|
|
"github.com/snapcore/snapd/errtracker"
|
|
"github.com/snapcore/snapd/osutil"
|
|
"github.com/snapcore/snapd/release"
|
|
"github.com/snapcore/snapd/snapdenv"
|
|
"github.com/snapcore/snapd/testutil"
|
|
)
|
|
|
|
// Hook up check.v1 into the "go test" runner
|
|
func Test(t *testing.T) { TestingT(t) }
|
|
|
|
type ErrtrackerTestSuite struct {
|
|
testutil.BaseTest
|
|
|
|
tmpdir string
|
|
|
|
hostBuildID string
|
|
coreBuildID string
|
|
distroRelease string
|
|
}
|
|
|
|
var _ = Suite(&ErrtrackerTestSuite{})
|
|
|
|
var truePath = osutil.LookPathDefault("true", "/bin/true")
|
|
var falsePath = osutil.LookPathDefault("false", "/bin/false")
|
|
|
|
const someJournalEntry = "Mar 29 22:08:00 localhost kernel: [81B blob data]"
|
|
|
|
func (s *ErrtrackerTestSuite) SetUpTest(c *C) {
|
|
s.BaseTest.SetUpTest(c)
|
|
|
|
s.tmpdir = c.MkDir()
|
|
dirs.SetRootDir(s.tmpdir)
|
|
|
|
p := filepath.Join(s.tmpdir, "machine-id")
|
|
err := ioutil.WriteFile(p, []byte("bbb1a6a5bcdb418380056a2d759c3f7c"), 0644)
|
|
c.Assert(err, IsNil)
|
|
s.AddCleanup(errtracker.MockMachineIDPaths([]string{p}))
|
|
s.AddCleanup(errtracker.MockHostSnapd(truePath))
|
|
s.AddCleanup(errtracker.MockCoreSnapd(falsePath))
|
|
s.AddCleanup(errtracker.MockReExec(func() string {
|
|
return "yes"
|
|
}))
|
|
mockDetectVirt := testutil.MockCommand(c, "systemd-detect-virt", "echo none")
|
|
s.AddCleanup(mockDetectVirt.Restore)
|
|
|
|
s.hostBuildID, err = osutil.ReadBuildID(truePath)
|
|
c.Assert(err, IsNil)
|
|
s.coreBuildID, err = osutil.ReadBuildID(falsePath)
|
|
c.Assert(err, IsNil)
|
|
if release.ReleaseInfo.ID == "ubuntu" {
|
|
s.distroRelease = fmt.Sprintf("%s %s", strings.Title(release.ReleaseInfo.ID), release.ReleaseInfo.VersionID)
|
|
} else {
|
|
s.distroRelease = fmt.Sprintf("%s %s", release.ReleaseInfo.ID, release.ReleaseInfo.VersionID)
|
|
}
|
|
|
|
mockCpuinfo := filepath.Join(s.tmpdir, "cpuinfo")
|
|
mockSelfCmdline := filepath.Join(s.tmpdir, "self.cmdline")
|
|
mockSelfExe := filepath.Join(s.tmpdir, "self.exe")
|
|
mockSelfCwd := filepath.Join(s.tmpdir, "self.cwd")
|
|
|
|
c.Assert(ioutil.WriteFile(mockCpuinfo, []byte(`
|
|
processor : 0
|
|
bugs : very yes
|
|
etc : ...
|
|
|
|
processor : 42
|
|
bugs : very yes
|
|
`[1:]), 0644), IsNil)
|
|
c.Assert(ioutil.WriteFile(mockSelfCmdline, []byte("foo\x00bar\x00baz"), 0644), IsNil)
|
|
c.Assert(os.Symlink("target of /proc/self/exe", mockSelfExe), IsNil)
|
|
c.Assert(os.Symlink("target of /proc/self/cwd", mockSelfCwd), IsNil)
|
|
|
|
s.AddCleanup(errtracker.MockOsGetenv(func(s string) string {
|
|
switch s {
|
|
case "SHELL":
|
|
return "/bin/sh"
|
|
case "XDG_CURRENT_DESKTOP":
|
|
return "Unity"
|
|
}
|
|
return ""
|
|
}))
|
|
s.AddCleanup(errtracker.MockProcCpuinfo(mockCpuinfo))
|
|
s.AddCleanup(errtracker.MockProcSelfCmdline(mockSelfCmdline))
|
|
s.AddCleanup(errtracker.MockProcSelfExe(mockSelfExe))
|
|
s.AddCleanup(errtracker.MockProcSelfCwd(mockSelfCwd))
|
|
s.AddCleanup(testutil.MockCommand(c, "journalctl", "echo "+someJournalEntry).Restore)
|
|
|
|
mockCmd := testutil.MockCommand(c, "systemctl", "echo enabled; exit 0")
|
|
s.AddCleanup(mockCmd.Restore)
|
|
}
|
|
|
|
func (s *ErrtrackerTestSuite) TestReport(c *C) {
|
|
n := 0
|
|
identifier := ""
|
|
|
|
snapConfineProfile := filepath.Join(s.tmpdir, "/etc/apparmor.d/usr.lib.snapd.snap-confine")
|
|
err := os.MkdirAll(filepath.Dir(snapConfineProfile), 0755)
|
|
c.Assert(err, IsNil)
|
|
err = ioutil.WriteFile(snapConfineProfile, []byte("# fake profile of snap-confine"), 0644)
|
|
c.Assert(err, IsNil)
|
|
|
|
err = ioutil.WriteFile(snapConfineProfile+".dpkg-new", []byte{0}, 0644)
|
|
c.Assert(err, IsNil)
|
|
err = ioutil.WriteFile(snapConfineProfile+".real", []byte{0}, 0644)
|
|
c.Assert(err, IsNil)
|
|
err = ioutil.WriteFile(snapConfineProfile+".real.dpkg-new", []byte{0}, 0644)
|
|
c.Assert(err, IsNil)
|
|
|
|
prev := errtracker.SnapdVersion
|
|
defer func() { errtracker.SnapdVersion = prev }()
|
|
errtracker.SnapdVersion = "some-snapd-version"
|
|
|
|
handler := func(w http.ResponseWriter, r *http.Request) {
|
|
switch n {
|
|
case 0:
|
|
c.Check(r.Method, Equals, "POST")
|
|
c.Check(r.URL.Path, Matches, "/[a-z0-9]+")
|
|
identifier = r.URL.Path
|
|
b, err := ioutil.ReadAll(r.Body)
|
|
c.Assert(err, IsNil)
|
|
|
|
var data map[string]string
|
|
err = bson.Unmarshal(b, &data)
|
|
c.Assert(err, IsNil)
|
|
c.Check(data, DeepEquals, map[string]string{
|
|
"DistroRelease": s.distroRelease,
|
|
"HostSnapdBuildID": s.hostBuildID,
|
|
"CoreSnapdBuildID": s.coreBuildID,
|
|
"SnapdVersion": "some-snapd-version",
|
|
"Date": "Fri Feb 17 09:51:00 2017",
|
|
"KernelVersion": osutil.KernelVersion(),
|
|
"ErrorMessage": "failed to do stuff",
|
|
"DuplicateSignature": "[failed to do stuff]",
|
|
"Architecture": arch.DpkgArchitecture(),
|
|
"DidSnapdReExec": "yes",
|
|
|
|
"ProblemType": "Snap",
|
|
"Snap": "some-snap",
|
|
"Channel": "beta",
|
|
|
|
"ProcCpuinfoMinimal": "processor\t: 42\nbugs\t\t: very yes\n",
|
|
"ExecutablePath": "target of /proc/self/exe",
|
|
"ProcCwd": "target of /proc/self/cwd",
|
|
"ProcCmdline": "foo\x00bar\x00baz",
|
|
"ProcEnviron": "SHELL=/bin/sh",
|
|
"JournalError": someJournalEntry + "\n",
|
|
"SourcePackage": "snapd",
|
|
"CurrentDesktop": "Unity",
|
|
"DetectedVirt": "none",
|
|
|
|
"MD5SumSnapConfineAppArmorProfile": "7a7aa5f21063170c1991b84eb8d86de1",
|
|
"MD5SumSnapConfineAppArmorProfileDpkgNew": "93b885adfe0da089cdf634904fd59f71",
|
|
"MD5SumSnapConfineAppArmorProfileReal": "93b885adfe0da089cdf634904fd59f71",
|
|
"MD5SumSnapConfineAppArmorProfileRealDpkgNew": "93b885adfe0da089cdf634904fd59f71",
|
|
})
|
|
fmt.Fprintf(w, "c14388aa-f78d-11e6-8df0-fa163eaf9b83 OOPSID")
|
|
case 1:
|
|
c.Check(r.Method, Equals, "POST")
|
|
c.Check(r.URL.Path, Matches, identifier)
|
|
fmt.Fprintf(w, "xxxxx-f78d-11e6-8df0-fa163eaf9b83 OOPSID")
|
|
default:
|
|
c.Fatalf("expected one request, got %d", n+1)
|
|
}
|
|
|
|
n++
|
|
}
|
|
|
|
server := httptest.NewServer(http.HandlerFunc(handler))
|
|
defer server.Close()
|
|
restorer := errtracker.MockCrashDbURL(server.URL)
|
|
defer restorer()
|
|
restorer = errtracker.MockTimeNow(func() time.Time { return time.Date(2017, 2, 17, 9, 51, 0, 0, time.UTC) })
|
|
defer restorer()
|
|
|
|
id, err := errtracker.Report("some-snap", "failed to do stuff", "[failed to do stuff]", map[string]string{
|
|
"Channel": "beta",
|
|
})
|
|
c.Check(err, IsNil)
|
|
c.Check(id, Equals, "c14388aa-f78d-11e6-8df0-fa163eaf9b83 OOPSID")
|
|
c.Check(n, Equals, 1)
|
|
|
|
// run again with the *same* dupSig and verify that it won't send
|
|
// that again
|
|
id, err = errtracker.Report("some-snap", "failed to do stuff", "[failed to do stuff]", map[string]string{
|
|
"Channel": "beta",
|
|
})
|
|
c.Check(err, IsNil)
|
|
c.Check(id, Equals, "already-reported")
|
|
c.Check(n, Equals, 1)
|
|
|
|
// run again with different data, verify identifier is unchanged
|
|
id, err = errtracker.Report("some-other-snap", "failed to do more stuff", "[failed to do more stuff]", nil)
|
|
c.Check(err, IsNil)
|
|
c.Check(id, Equals, "xxxxx-f78d-11e6-8df0-fa163eaf9b83 OOPSID")
|
|
c.Check(n, Equals, 2)
|
|
}
|
|
|
|
func (s *ErrtrackerTestSuite) TestReportUnderTesting(c *C) {
|
|
defer snapdenv.MockTesting(true)()
|
|
|
|
n := 0
|
|
prev := errtracker.SnapdVersion
|
|
defer func() { errtracker.SnapdVersion = prev }()
|
|
errtracker.SnapdVersion = "some-snapd-version"
|
|
|
|
handler := func(w http.ResponseWriter, r *http.Request) {
|
|
n++
|
|
}
|
|
|
|
server := httptest.NewServer(http.HandlerFunc(handler))
|
|
defer server.Close()
|
|
restorer := errtracker.MockCrashDbURL(server.URL)
|
|
defer restorer()
|
|
restorer = errtracker.MockTimeNow(func() time.Time { return time.Date(2017, 2, 17, 9, 51, 0, 0, time.UTC) })
|
|
defer restorer()
|
|
|
|
id, err := errtracker.Report("some-snap", "failed to do stuff", "[failed to do stuff]", map[string]string{
|
|
"Channel": "beta",
|
|
})
|
|
c.Check(err, IsNil)
|
|
c.Check(id, Equals, "oops-not-sent")
|
|
c.Check(n, Equals, 0)
|
|
}
|
|
|
|
func (s *ErrtrackerTestSuite) TestTriesAllKnownMachineIDs(c *C) {
|
|
p := filepath.Join(c.MkDir(), "machine-id")
|
|
machineID := []byte("bbb1a6a5bcdb418380056a2d759c3f7c")
|
|
err := ioutil.WriteFile(p, machineID, 0644)
|
|
c.Assert(err, IsNil)
|
|
s.AddCleanup(errtracker.MockMachineIDPaths([]string{"/does/not/exist", p}))
|
|
|
|
n := 0
|
|
var identifiers []string
|
|
handler := func(w http.ResponseWriter, r *http.Request) {
|
|
identifiers = append(identifiers, r.URL.Path)
|
|
n++
|
|
}
|
|
|
|
server := httptest.NewServer(http.HandlerFunc(handler))
|
|
defer server.Close()
|
|
restorer := errtracker.MockCrashDbURL(server.URL)
|
|
defer restorer()
|
|
restorer = errtracker.MockTimeNow(func() time.Time { return time.Date(2017, 2, 17, 9, 51, 0, 0, time.UTC) })
|
|
defer restorer()
|
|
|
|
_, err = errtracker.Report("some-snap", "failed to do stuff", "[failed to do stuff]", map[string]string{
|
|
"Channel": "beta",
|
|
})
|
|
c.Check(err, IsNil)
|
|
c.Check(n, Equals, 1)
|
|
c.Check(identifiers, DeepEquals, []string{fmt.Sprintf("/%x", sha512.Sum512(machineID))})
|
|
}
|
|
|
|
func (s *ErrtrackerTestSuite) TestReportRepair(c *C) {
|
|
n := 0
|
|
prev := errtracker.SnapdVersion
|
|
defer func() { errtracker.SnapdVersion = prev }()
|
|
errtracker.SnapdVersion = "some-snapd-version"
|
|
|
|
handler := func(w http.ResponseWriter, r *http.Request) {
|
|
switch n {
|
|
case 0:
|
|
c.Check(r.Method, Equals, "POST")
|
|
c.Check(r.URL.Path, Matches, "/[a-z0-9]+")
|
|
b, err := ioutil.ReadAll(r.Body)
|
|
c.Assert(err, IsNil)
|
|
|
|
var data map[string]string
|
|
err = bson.Unmarshal(b, &data)
|
|
c.Assert(err, IsNil)
|
|
c.Check(data, DeepEquals, map[string]string{
|
|
"DistroRelease": s.distroRelease,
|
|
"HostSnapdBuildID": s.hostBuildID,
|
|
"CoreSnapdBuildID": s.coreBuildID,
|
|
"SnapdVersion": "some-snapd-version",
|
|
"Date": "Fri Feb 17 09:51:00 2017",
|
|
"KernelVersion": osutil.KernelVersion(),
|
|
"Architecture": arch.DpkgArchitecture(),
|
|
"DidSnapdReExec": "yes",
|
|
|
|
"ProblemType": "Repair",
|
|
"Repair": `"repair (1; brand-id:canonical)"`,
|
|
"ErrorMessage": "failure in script",
|
|
"DuplicateSignature": "[dupSig]",
|
|
"BrandID": "canonical",
|
|
|
|
"ProcCpuinfoMinimal": "processor\t: 42\nbugs\t\t: very yes\n",
|
|
"ExecutablePath": "target of /proc/self/exe",
|
|
"ProcCwd": "target of /proc/self/cwd",
|
|
"ProcCmdline": "foo\x00bar\x00baz",
|
|
"ProcEnviron": "SHELL=/bin/sh",
|
|
"JournalError": someJournalEntry + "\n",
|
|
"SourcePackage": "snapd",
|
|
"CurrentDesktop": "Unity",
|
|
"DetectedVirt": "none",
|
|
})
|
|
fmt.Fprintf(w, "c14388aa-f78d-11e6-8df0-fa163eaf9b83 OOPSID")
|
|
default:
|
|
c.Fatalf("expected one request, got %d", n+1)
|
|
}
|
|
|
|
n++
|
|
}
|
|
|
|
server := httptest.NewServer(http.HandlerFunc(handler))
|
|
defer server.Close()
|
|
restorer := errtracker.MockCrashDbURL(server.URL)
|
|
defer restorer()
|
|
restorer = errtracker.MockTimeNow(func() time.Time { return time.Date(2017, 2, 17, 9, 51, 0, 0, time.UTC) })
|
|
defer restorer()
|
|
|
|
id, err := errtracker.ReportRepair(`"repair (1; brand-id:canonical)"`, "failure in script", "[dupSig]", map[string]string{
|
|
"BrandID": "canonical",
|
|
})
|
|
c.Check(err, IsNil)
|
|
c.Check(id, Equals, "c14388aa-f78d-11e6-8df0-fa163eaf9b83 OOPSID")
|
|
c.Check(n, Equals, 1)
|
|
}
|
|
|
|
func (s *ErrtrackerTestSuite) TestReportWithWhoopsieDisabled(c *C) {
|
|
mockCmd := testutil.MockCommand(c, "systemctl", "echo disabled; exit 1")
|
|
defer mockCmd.Restore()
|
|
|
|
handler := func(w http.ResponseWriter, r *http.Request) {
|
|
c.Fatalf("The server should not be hit from here")
|
|
}
|
|
server := httptest.NewServer(http.HandlerFunc(handler))
|
|
defer server.Close()
|
|
restorer := errtracker.MockCrashDbURL(server.URL)
|
|
defer restorer()
|
|
|
|
id, err := errtracker.Report("some-snap", "failed to do stuff", "[failed to do stuff]", nil)
|
|
c.Check(err, IsNil)
|
|
c.Check(id, Equals, "")
|
|
}
|
|
|
|
func (s *ErrtrackerTestSuite) TestReportWithNoWhoopsieInstalled(c *C) {
|
|
mockCmd := testutil.MockCommand(c, "systemctl", "echo Failed to get unit file state for whoopsie.service; exit 1")
|
|
defer mockCmd.Restore()
|
|
|
|
n := 0
|
|
handler := func(w http.ResponseWriter, r *http.Request) {
|
|
fmt.Fprintf(w, "1234-oopsid")
|
|
n++
|
|
}
|
|
server := httptest.NewServer(http.HandlerFunc(handler))
|
|
defer server.Close()
|
|
restorer := errtracker.MockCrashDbURL(server.URL)
|
|
defer restorer()
|
|
|
|
id, err := errtracker.Report("some-snap", "failed to do stuff", "[failed to do stuff]", nil)
|
|
c.Check(err, IsNil)
|
|
c.Check(id, Equals, "1234-oopsid")
|
|
c.Check(n, Equals, 1)
|
|
}
|
|
|
|
func (s *ErrtrackerTestSuite) TestProcCpuinfo(c *C) {
|
|
fn := filepath.Join(s.tmpdir, "cpuinfo")
|
|
// validity check
|
|
buf, err := ioutil.ReadFile(fn)
|
|
c.Assert(err, IsNil)
|
|
c.Check(string(buf), Equals, `
|
|
processor : 0
|
|
bugs : very yes
|
|
etc : ...
|
|
|
|
processor : 42
|
|
bugs : very yes
|
|
`[1:])
|
|
|
|
// just the last processor entry
|
|
c.Check(errtracker.ProcCpuinfoMinimal(), Equals, `
|
|
processor : 42
|
|
bugs : very yes
|
|
`[1:])
|
|
|
|
// if no processor line, just return the whole thing
|
|
c.Assert(ioutil.WriteFile(fn, []byte("yadda yadda\n"), 0644), IsNil)
|
|
c.Check(errtracker.ProcCpuinfoMinimal(), Equals, "yadda yadda\n")
|
|
|
|
c.Assert(os.Remove(fn), IsNil)
|
|
c.Check(errtracker.ProcCpuinfoMinimal(), Matches, "error: .* no such file or directory")
|
|
}
|
|
|
|
func (s *ErrtrackerTestSuite) TestProcExe(c *C) {
|
|
c.Check(errtracker.ProcExe(), Equals, "target of /proc/self/exe")
|
|
c.Assert(os.Remove(filepath.Join(s.tmpdir, "self.exe")), IsNil)
|
|
c.Check(errtracker.ProcExe(), Matches, "error: .* no such file or directory")
|
|
}
|
|
|
|
func (s *ErrtrackerTestSuite) TestProcCwd(c *C) {
|
|
c.Check(errtracker.ProcCwd(), Equals, "target of /proc/self/cwd")
|
|
c.Assert(os.Remove(filepath.Join(s.tmpdir, "self.cwd")), IsNil)
|
|
c.Check(errtracker.ProcCwd(), Matches, "error: .* no such file or directory")
|
|
}
|
|
|
|
func (s *ErrtrackerTestSuite) TestProcCmdline(c *C) {
|
|
c.Check(errtracker.ProcCmdline(), Equals, "foo\x00bar\x00baz")
|
|
c.Assert(os.Remove(filepath.Join(s.tmpdir, "self.cmdline")), IsNil)
|
|
c.Check(errtracker.ProcCmdline(), Matches, "error: .* no such file or directory")
|
|
}
|
|
|
|
func (s *ErrtrackerTestSuite) TestJournalError(c *C) {
|
|
jctl := testutil.MockCommand(c, "journalctl", "echo "+someJournalEntry)
|
|
defer jctl.Restore()
|
|
c.Check(errtracker.JournalError(), Equals, someJournalEntry+"\n")
|
|
c.Check(jctl.Calls(), DeepEquals, [][]string{
|
|
{"journalctl", "-b", "--priority=warning..err", "--lines=1000"},
|
|
})
|
|
}
|
|
|
|
func (s *ErrtrackerTestSuite) TestJournalErrorSilentError(c *C) {
|
|
jctl := testutil.MockCommand(c, "journalctl", "kill $$")
|
|
defer jctl.Restore()
|
|
c.Check(errtracker.JournalError(), Matches, "error: signal: [Tt]erminated")
|
|
c.Check(jctl.Calls(), DeepEquals, [][]string{
|
|
{"journalctl", "-b", "--priority=warning..err", "--lines=1000"},
|
|
})
|
|
}
|
|
|
|
func (s *ErrtrackerTestSuite) TestJournalErrorError(c *C) {
|
|
jctl := testutil.MockCommand(c, "journalctl", "echo OOPS; exit 1")
|
|
defer jctl.Restore()
|
|
c.Check(errtracker.JournalError(), Equals, "OOPS\n\nerror: exit status 1")
|
|
c.Check(jctl.Calls(), DeepEquals, [][]string{
|
|
{"journalctl", "-b", "--priority=warning..err", "--lines=1000"},
|
|
})
|
|
}
|
|
|
|
func (s *ErrtrackerTestSuite) TestEnviron(c *C) {
|
|
defer errtracker.MockOsGetenv(func(s string) string {
|
|
switch s {
|
|
case "SHELL":
|
|
// marked as safe
|
|
return "/bin/sh"
|
|
case "GPG_AGENT_INFO":
|
|
// not marked as safe
|
|
return ".gpg-agent:0:1"
|
|
case "TERM":
|
|
// not really set
|
|
return ""
|
|
case "PATH":
|
|
// special handling from here down
|
|
return "/something/random:/sbin/:/home/ubuntu/bin:/bin:/snap/bin"
|
|
case "XDG_RUNTIME_DIR":
|
|
return "/some/thing"
|
|
case "LD_PRELOAD":
|
|
return "foo"
|
|
case "LD_LIBRARY_PATH":
|
|
return "bar"
|
|
}
|
|
return ""
|
|
})()
|
|
|
|
env := strings.Split(errtracker.Environ(), "\n")
|
|
sort.Strings(env)
|
|
|
|
c.Check(env, DeepEquals, []string{
|
|
"LD_LIBRARY_PATH=<set>",
|
|
"LD_PRELOAD=<set>",
|
|
// note also /sbin/ -> /sbin
|
|
"PATH=(custom):/sbin:(user):/bin:/snap/bin",
|
|
"SHELL=/bin/sh",
|
|
"XDG_RUNTIME_DIR=<set>",
|
|
})
|
|
}
|
|
|
|
func (s *ErrtrackerTestSuite) TestReportsDB(c *C) {
|
|
db, err := errtracker.NewReportsDB(filepath.Join(s.tmpdir, "foo.db"))
|
|
c.Assert(err, IsNil)
|
|
|
|
c.Check(db.AlreadyReported("some-dup-sig"), Equals, false)
|
|
|
|
err = db.MarkReported("some-dup-sig")
|
|
c.Check(err, IsNil)
|
|
|
|
c.Check(db.AlreadyReported("some-dup-sig"), Equals, true)
|
|
c.Check(db.AlreadyReported("other-dup-sig"), Equals, false)
|
|
}
|
|
|
|
func (s *ErrtrackerTestSuite) TestReportsDBCleanup(c *C) {
|
|
db, err := errtracker.NewReportsDB(filepath.Join(s.tmpdir, "foo.db"))
|
|
c.Assert(err, IsNil)
|
|
|
|
errtracker.SetReportDBCleanupTime(db, 1*time.Millisecond)
|
|
|
|
err = db.MarkReported("some-dup-sig")
|
|
c.Check(err, IsNil)
|
|
|
|
time.Sleep(10 * time.Millisecond)
|
|
err = db.MarkReported("other-dup-sig")
|
|
c.Check(err, IsNil)
|
|
|
|
// this one got cleaned out
|
|
c.Check(db.AlreadyReported("some-dup-sig"), Equals, false)
|
|
// this one is still fresh
|
|
c.Check(db.AlreadyReported("other-dup-sig"), Equals, true)
|
|
}
|
|
|
|
func (s *ErrtrackerTestSuite) TestReportsDBnilDoesNotCrash(c *C) {
|
|
db, err := errtracker.NewReportsDB("/proc/1/environ")
|
|
c.Assert(err, NotNil)
|
|
c.Check(db, IsNil)
|
|
|
|
c.Check(db.AlreadyReported("dupSig"), Equals, false)
|
|
c.Check(db.MarkReported("dupSig"), ErrorMatches, "cannot mark error report as reported with an uninitialized reports database")
|
|
}
|
|
|
|
func (s *ErrtrackerTestSuite) TestReportsDBnilDoesNotCrashOnReport(c *C) {
|
|
oldDbDir := dirs.ErrtrackerDbDir
|
|
dirs.ErrtrackerDbDir = "/proc/1/environ"
|
|
defer func() {
|
|
dirs.ErrtrackerDbDir = oldDbDir
|
|
}()
|
|
|
|
id, err := errtracker.Report("some-snap", "failed to do stuff", "[failed to do stuff]", nil)
|
|
c.Assert(err, ErrorMatches, "cannot open error reports database: open /proc/1/environ:.*")
|
|
c.Assert(id, Equals, "")
|
|
}
|