diff -Nru ubuntu-report-1.0.11/#1#input.txt ubuntu-report-1.1.0/#1#input.txt --- ubuntu-report-1.0.11/#1#input.txt 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-report-1.1.0/#1#input.txt 2018-05-30 13:39:35.000000000 +0000 @@ -0,0 +1,3 @@ +! TRAVIS input file +! Created with TRAVIS version compiled at Jan 14 2018 01:39:14 +! Input file written at Wed May 30 15:39:35 2018. diff -Nru ubuntu-report-1.0.11/#1#travis.log ubuntu-report-1.1.0/#1#travis.log --- ubuntu-report-1.0.11/#1#travis.log 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-report-1.1.0/#1#travis.log 2018-05-30 13:39:35.000000000 +0000 @@ -0,0 +1,84 @@ +Command line: +"travis setup releases" + + + ________ __ + / | / | + ########/ ______ ______ __ __ ##/ _______ + ## | / \ / \ / \ / | / | / | + ## | /###### | ###### | ## \ /##/ ## | /#######/ + ## | ## | ##/ / ## | ## /##/ ## | ## \ + ## | ## | /####### | ## ##/ ## | ###### | + ## | ## | ## ## | ###/ ## | / ##/ + ##/ ##/ #######/ #/ ##/ #######/ + + TRajectory Analyzer and VISualizer - Open-source freeware under GNU GPL v3 + + Copyright (c) Martin Brehm (2009-2017), University of Halle (Saale) + Martin Thomas (2012-2017) + Barbara Kirchner (2009-2017), University of Bonn + + http://www.travis-analyzer.de + + Please cite: M. Brehm, B. Kirchner: J. Chem. Inf. Model. 2011, 51 (8), pp 2007-2023. + + There is absolutely no warranty on any results obtained from TRAVIS. + + # Running on casanier at Wed May 30 15:39:35 2018 (PID 21809). + # Running in /home/didrocks/work/go/src/github.com/ubuntu/ubuntu-report + # Code version: Aug 12 2017, compiled at Jan 14 2018 01:39:14, compiler "7.2.0", GCC 7.2.0 + # Target platform: Linux, compile flags: DEBUG_ARRAYS + # Machine: int=4b, long=8b, addr=8b, 0xA0B0C0D0=D0,C0,B0,A0. + # User home: /home/didrocks, executable: /usr/bin/travis + # Input from terminal, Output to terminal + + >>> Please use a color scheme with dark background or specify "-nocolor"! <<< + + No configuration file found. + Writing default configuration to /home/didrocks/.travis.conf ... + +Unknown parameter: "setup". + + List of supported command line options: + + -p Loads position data from the specified trajectory file. + The file format may be *.xyz, *.pdb, *.lmp (LAMMPS), HISTORY (DLPOLY), or *.prmtop/*.mdcrd (Amber). + BQB format (*.bqb, *.btr, *.blist) is also supported. + -vel Reads atom velocities from file in addition to main trajectory. + Currently, only .xyz format is supported for velocity data. + -i Reads input from the specified text file. + + -config Load the specified configuration file. + -stream Treats input trajectory as a stream (e.g. named pipe): No fseek, etc. + -showconf Shows a tree structure of the configuration file. + -writeconf Writes the default configuration file, including all defines values. + + -verbose Show detailed information about what's going on. + -nocolor Executes TRAVIS in monochrome mode (suitable for white background). + -dimcolor Uses dim instead of bright colors. + + -credits Display a list of persons who contributed to TRAVIS. + -help, -? Shows this help. + + If only one argument is specified, it is assumed to be the name of a trajectory file. + If argument is specified at all, TRAVIS asks for the trajectory file to open. + + + Note: To show a list of all persons who contributed to TRAVIS, + please add "-credits" to your command line arguments, or set the + variable "SHOWCREDITS" to "TRUE" in your travis.conf file. + + Source code from other projects used in TRAVIS: + - lmfit from Joachim Wuttke + - kiss_fft from Mark Borgerding + - voro++ from Chris Rycroft + + http://www.travis-analyzer.de + + Please cite the following articles: + + * "TRAVIS - A Free Analyzer and Visualizer for Monte Carlo and Molecular Dynamics Trajectories", + M. Brehm, B. Kirchner; J. Chem. Inf. Model. 2011, 51 (8), pp 2007-2023. + +*** The End *** + diff -Nru ubuntu-report-1.0.11/cmd/ubuntu-report/main.go ubuntu-report-1.1.0/cmd/ubuntu-report/main.go --- ubuntu-report-1.0.11/cmd/ubuntu-report/main.go 2018-04-05 15:12:53.000000000 +0000 +++ ubuntu-report-1.1.0/cmd/ubuntu-report/main.go 2018-05-25 09:07:25.000000000 +0000 @@ -110,6 +110,22 @@ send.Flags().StringVarP(&flagServerURL, "url", "u", sender.BaseURL, "server url to send report to. Leave empty for default.") rootCmd.AddCommand(send) + service := &cobra.Command{ + Use: "service", + Short: "Try to send periodically previously collected data once network if previous send was unsuccessful", + Args: cobra.NoArgs, + Hidden: true, + Run: func(cmd *cobra.Command, args []string) { + err := sysmetrics.SendPendingReport(flagServerURL) + if err != nil { + log.Errorf(utils.ErrFormat, err) + os.Exit(1) + } + }, + } + service.Flags().StringVarP(&flagServerURL, "url", "u", sender.BaseURL, "server url to send report to. Leave empty for default.") + rootCmd.AddCommand(service) + interactiveCmd := &cobra.Command{ Use: "interactive", Short: "Interactive mode, alias to running this tool without any subcommands.", diff -Nru ubuntu-report-1.0.11/cmd/ubuntu-report/main_test.go ubuntu-report-1.1.0/cmd/ubuntu-report/main_test.go --- ubuntu-report-1.0.11/cmd/ubuntu-report/main_test.go 2018-04-19 12:49:55.000000000 +0000 +++ ubuntu-report-1.1.0/cmd/ubuntu-report/main_test.go 2018-05-25 08:43:51.000000000 +0000 @@ -314,6 +314,77 @@ } } +func TestService(t *testing.T) { + helper.SkipIfShort(t) + + testCases := []struct { + name string + + shouldHitServer bool + }{ + {"regular send", true}, + } + for _, tc := range testCases { + tc := tc // capture range variable for parallel execution + t.Run(tc.name, func(t *testing.T) { + a := helper.Asserter{T: t} + + out, tearDown := helper.TempDir(t) + defer tearDown() + defer helper.ChangeEnv("XDG_CACHE_HOME", out)() + out = filepath.Join(out, "ubuntu-report") + + pendingReportData, err := ioutil.ReadFile(filepath.Join("testdata", "good", "ubuntu-report", "pending")) + if err != nil { + t.Fatalf("couldn't open pending report file: %v", err) + } + pendingReportPath := filepath.Join(out, "pending") + if err := os.MkdirAll(out, 0700); err != nil { + t.Fatal("couldn't create parent directory of pending report", err) + } + if err := ioutil.WriteFile(pendingReportPath, pendingReportData, 0644); err != nil { + t.Fatalf("couldn't copy pending report file to cache directory: %v", err) + } + + // we don't really care where we hit for this API integration test, internal ones test it + // and we don't really control /etc/os-release version and id. + // Same for report file + serverHit := false + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + serverHit = true + })) + defer ts.Close() + + cmd := generateRootCmd() + args := []string{"service", "--url", ts.URL} + cmd.SetArgs(args) + + cmdErrs := helper.RunFunctionWithTimeout(t, func() error { + var err error + _, err = cmd.ExecuteC() + return err + }) + + if err := <-cmdErrs; err != nil { + t.Fatal("got an error when expecting none:", err) + } + + a.Equal(serverHit, tc.shouldHitServer) + + if _, pendingReportErr := os.Stat(pendingReportPath); os.IsExist(pendingReportErr) { + t.Errorf("we expected the pending report to be removed and it wasn't") + } + + p := filepath.Join(out, helper.FindInDirectory(t, "", out)) + got, err := ioutil.ReadFile(p) + if err != nil { + t.Fatalf("couldn't open report file %s", out) + } + a.Equal(got, pendingReportData) + }) + } +} + // scanLinesOrQuestion is copy of ScanLines, adding the expected question string as we don't return here func scanLinesOrQuestion(data []byte, atEOF bool) (advance int, token []byte, err error) { if atEOF && len(data) == 0 { diff -Nru ubuntu-report-1.0.11/cmd/ubuntu-report/testdata/good/ubuntu-report/pending ubuntu-report-1.1.0/cmd/ubuntu-report/testdata/good/ubuntu-report/pending --- ubuntu-report-1.0.11/cmd/ubuntu-report/testdata/good/ubuntu-report/pending 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-report-1.1.0/cmd/ubuntu-report/testdata/good/ubuntu-report/pending 2018-05-25 08:43:51.000000000 +0000 @@ -0,0 +1,4 @@ +{ + "Version": "foo", + "SomeData": true +} diff -Nru ubuntu-report-1.0.11/debian/changelog ubuntu-report-1.1.0/debian/changelog --- ubuntu-report-1.0.11/debian/changelog 2018-04-19 13:00:16.000000000 +0000 +++ ubuntu-report-1.1.0/debian/changelog 2018-05-31 07:58:03.000000000 +0000 @@ -1,3 +1,15 @@ +ubuntu-report (1.1.0) bionic; urgency=medium + + * Delay reporting of system metrics when there is no network. + A service then kicks in and try to report with exponential + backoff until success (LP: #1774354) + * Ensure that LANG is the user's language reported even in OEM + mode (LP: #1765672) + * Collect physical screen size (LP: #1771976) + * Incorrect regex for GPU info (LP: #1765614) + + -- Didier Roche Thu, 31 May 2018 09:58:03 +0200 + ubuntu-report (1.0.11) bionic; urgency=medium * Use sys_vendor to determine vendor (LP: #1765400) diff -Nru ubuntu-report-1.0.11/debian/rules ubuntu-report-1.1.0/debian/rules --- ubuntu-report-1.0.11/debian/rules 2018-04-18 07:42:29.000000000 +0000 +++ ubuntu-report-1.1.0/debian/rules 2018-05-25 08:43:51.000000000 +0000 @@ -27,6 +27,7 @@ ln -s libsysmetrics.so.1 debian/tmp/usr/lib/$(DEB_HOST_MULTIARCH)/libsysmetrics.so cp -a $(artefactsdir)/libsysmetrics.h debian/tmp/usr/include/sysmetrics sed -e s/DEB_HOST_MULTIARCH/$(DEB_HOST_MULTIARCH)/ debian/sysmetrics.pc.in > debian/tmp/usr/lib/$(DEB_HOST_MULTIARCH)/pkgconfig/sysmetrics.pc + mkdir -p debian/ubuntu-report/etc/systemd/user/default.target.wants/ dh_auto_install override_dh_missing: diff -Nru ubuntu-report-1.0.11/debian/ubuntu-report.install ubuntu-report-1.1.0/debian/ubuntu-report.install --- ubuntu-report-1.0.11/debian/ubuntu-report.install 2018-03-27 11:33:25.000000000 +0000 +++ ubuntu-report-1.1.0/debian/ubuntu-report.install 2018-05-25 08:43:51.000000000 +0000 @@ -1,3 +1,4 @@ usr/bin obj-*/build/ubuntu-report usr/share/bash-completion/completions/ obj-*/build/_ubuntu-report usr/share/zsh/vendor-completions/ +systemd/ubuntu-report.* usr/lib/systemd/user diff -Nru ubuntu-report-1.0.11/debian/ubuntu-report.links ubuntu-report-1.1.0/debian/ubuntu-report.links --- ubuntu-report-1.0.11/debian/ubuntu-report.links 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-report-1.1.0/debian/ubuntu-report.links 2018-05-25 08:43:51.000000000 +0000 @@ -0,0 +1 @@ +usr/lib/systemd/user/ubuntu-report.path etc/systemd/user/default.target.wants/ubuntu-report.path diff -Nru ubuntu-report-1.0.11/input.txt ubuntu-report-1.1.0/input.txt --- ubuntu-report-1.0.11/input.txt 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-report-1.1.0/input.txt 2018-05-30 13:40:15.000000000 +0000 @@ -0,0 +1,3 @@ +! TRAVIS input file +! Created with TRAVIS version compiled at Jan 14 2018 01:39:14 +! Input file written at Wed May 30 15:40:15 2018. diff -Nru ubuntu-report-1.0.11/internal/metrics/binmocks_test.go ubuntu-report-1.1.0/internal/metrics/binmocks_test.go --- ubuntu-report-1.0.11/internal/metrics/binmocks_test.go 2018-04-17 08:08:02.000000000 +0000 +++ ubuntu-report-1.1.0/internal/metrics/binmocks_test.go 2018-05-25 08:43:51.000000000 +0000 @@ -54,11 +54,15 @@ case "multiple gpus": fmt.Println(regularOutput) fmt.Println("00:02.0 0300: 8086:0127 (rev 09)") + case "no revision number": + fmt.Println("00:02.0 0300: 8086:0126") case "no gpu": fmt.Println(`00:00.0 0600: 8086:0104 (rev 09) 00:16.0 0780: 8086:1c3a (rev 04) 00:16.3 0700: 8086:1c3d (rev 04) 00:19.0 0200: 8086:1502 (rev 04)`) + case "hexa numbers": + fmt.Println("00:02.0 0300: 8b86:a126 (rev 09)") case "empty": case "malformed gpu line": fmt.Println("00:02.0 0300: 80860127 (rev 09)") @@ -108,6 +112,11 @@ fmt.Println(`VGA-1 connected 1920x1080+0+0 (normal left inverted right x axis y axis) 510mm x 287mm 1920x1080 60.00 59.94 50.00* 60.05 60.00 50.04 1600x1200 60.00 +`) + case "no specified screen size": + fmt.Println(`VGA-1 connected 1920x1080+0+0 (normal left inverted right x axis y axis) + 1920x1080 60.00*+ + 1600x1200 60.00 + 1680x1050 59.95 `) case "no chosen resolution": fmt.Println(`VGA-1 connected 1920x1080+0+0 (normal left inverted right x axis y axis) 510mm x 287mm 1920x1080 60.00 @@ -115,7 +124,7 @@ 1680x1050 59.95 `) case "empty": case "malformed screen line": - fmt.Println(`VGA-1 connected 1920x1080+0+0 (normal left inverted right x axis y axis) 510mm x 287mm + fmt.Println(`VGA-1 connected 1920x1080+0+0 (normal left inverted right x axis y axis) 510m x 287mm 1920x108160.00*+`) case "garbage": fmt.Println(garbageOutput) diff -Nru ubuntu-report-1.0.11/internal/metrics/cmd.go ubuntu-report-1.1.0/internal/metrics/cmd.go --- ubuntu-report-1.0.11/internal/metrics/cmd.go 2018-04-17 08:08:02.000000000 +0000 +++ ubuntu-report-1.1.0/internal/metrics/cmd.go 2018-05-25 08:43:51.000000000 +0000 @@ -15,7 +15,7 @@ r := runCmd(m.gpuInfoCmd) - results, err := filterAll(r, `^.* 0300: (.*) \(rev .*\)$`) + results, err := filterAll(r, `^.* 0300: ([a-zA-Z0-9]+:[a-zA-Z0-9]+)( \(rev .*\))?$`) if err != nil { log.Infof("couldn't get GPU info: "+utils.ErrFormat, err) return nil @@ -38,19 +38,29 @@ r := runCmd(m.screenInfoCmd) - results, err := filterAll(r, `^ +(.*)\*`) + var results []string + results, err := filterAll(r, `^(?: +(.*)\*|.* connected .* (\d+mm x \d+mm))`) if err != nil { log.Infof("couldn't get Screen info: "+utils.ErrFormat, err) return nil } + var lastSize string for _, screeninfo := range results { + if strings.Index(screeninfo, "mm") > -1 { + lastSize = strings.Replace(screeninfo, " ", "", -1) + continue + } i := strings.Fields(screeninfo) if len(i) < 2 { - log.Infof("screen info should be of form 'resolution [freqs]*', got: %s", screeninfo) + log.Infof("screen info should be either a screen physical size (connected) or a a resolution + freq, got: %s", screeninfo) + continue + } + if lastSize == "" { + log.Infof("We couldn't get physical info size prior to Resolution and Frequency information.") continue } - screens = append(screens, screenInfo{Resolution: i[0], Frequency: i[len(i)-1]}) + screens = append(screens, screenInfo{Size: lastSize, Resolution: i[0], Frequency: i[len(i)-1]}) } return screens diff -Nru ubuntu-report-1.0.11/internal/metrics/filter.go ubuntu-report-1.1.0/internal/metrics/filter.go --- ubuntu-report-1.0.11/internal/metrics/filter.go 2018-03-12 17:28:16.000000000 +0000 +++ ubuntu-report-1.1.0/internal/metrics/filter.go 2018-05-25 08:43:51.000000000 +0000 @@ -25,7 +25,12 @@ for scanner.Scan() { m := re.FindStringSubmatch(scanner.Text()) if m != nil { - results <- filterResult{r: strings.TrimSpace(m[1])} + // we want the first non empty match (can be null in case of alternative regexp) + var match string + for i := 1; match == "" && i < len(m); i++ { + match = strings.TrimSpace(m[i]) + } + results <- filterResult{r: match} } } diff -Nru ubuntu-report-1.0.11/internal/metrics/internals_test.go ubuntu-report-1.1.0/internal/metrics/internals_test.go --- ubuntu-report-1.0.11/internal/metrics/internals_test.go 2018-04-17 08:08:02.000000000 +0000 +++ ubuntu-report-1.1.0/internal/metrics/internals_test.go 2018-05-25 08:43:51.000000000 +0000 @@ -351,7 +351,9 @@ }{ {"one gpu", []gpuInfo{{"8086", "0126"}}}, {"multiple gpus", []gpuInfo{{"8086", "0126"}, {"8086", "0127"}}}, + {"no revision number", []gpuInfo{{"8086", "0126"}}}, {"no gpu", nil}, + {"hexa numbers", []gpuInfo{{"8b86", "a126"}}}, {"empty", nil}, {"malformed gpu line", nil}, {"garbage", nil}, @@ -382,15 +384,16 @@ want []screenInfo }{ - {"one screen", []screenInfo{{"1366x768", "60.02"}}}, - {"multiple screens", []screenInfo{{"1366x768", "60.02"}, {"1920x1080", "60.00"}}}, + {"one screen", []screenInfo{{"277mmx156mm", "1366x768", "60.02"}}}, + {"multiple screens", []screenInfo{{"277mmx156mm", "1366x768", "60.02"}, {"510mmx287mm", "1920x1080", "60.00"}}}, {"no screen", nil}, - {"chosen resolution not first", []screenInfo{{"1600x1200", "60.00"}}}, + {"chosen resolution not first", []screenInfo{{"510mmx287mm", "1600x1200", "60.00"}}}, + {"no specified screen size", nil}, {"no chosen resolution", nil}, - {"chosen resolution not prefered", []screenInfo{{"1920x1080", "60.00"}}}, - {"multiple frequencies for resolution", []screenInfo{{"1920x1080", "60.00"}}}, - {"multiple frequencies select other resolution", []screenInfo{{"1920x1080", "50.00"}}}, - {"multiple frequencies select other resolution on non preferred", []screenInfo{{"1920x1080", "50.00"}}}, + {"chosen resolution not prefered", []screenInfo{{"510mmx287mm", "1920x1080", "60.00"}}}, + {"multiple frequencies for resolution", []screenInfo{{"510mmx287mm", "1920x1080", "60.00"}}}, + {"multiple frequencies select other resolution", []screenInfo{{"510mmx287mm", "1920x1080", "50.00"}}}, + {"multiple frequencies select other resolution on non preferred", []screenInfo{{"510mmx287mm", "1920x1080", "50.00"}}}, {"empty", nil}, {"malformed screen line", nil}, {"garbage", nil}, @@ -477,6 +480,42 @@ } } +func TestGetLanguage(t *testing.T) { + t.Parallel() + + testCases := []struct { + name string + env map[string]string + + want string + }{ + {"regular", map[string]string{"LANG": "fr_FR.UTF-8", "LANGUAGE": "fr_FR.UTF-8"}, "fr_FR"}, + {"LC_ALL override all", map[string]string{ + "LC_ALL": "en_US.UTF-8", "LANG": "fr_FR.UTF-8", "LANGUAGE": "fr_FR.UTF-8"}, "en_US"}, + {"LANG override LANGUAGE", + map[string]string{"LANG": "en_US.UTF-8", "LANGUAGE": "fr_FR.UTF-8"}, "en_US"}, + {"LANGUAGE only", + map[string]string{"LANGUAGE": "fr_FR.UTF-8"}, "fr_FR"}, + {"only first in LANGUAGE list", + map[string]string{"LANGUAGE": "fr_FR.UTF-8:en_US.UTF8"}, "fr_FR"}, + {"without encoding", map[string]string{"LANG": "fr_FR", "LANGUAGE": "fr_FR"}, "fr_FR"}, + {"none", nil, ""}, + } + for _, tc := range testCases { + tc := tc // capture range variable for parallel execution + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + a := helper.Asserter{T: t} + + m := newTestMetrics(t, WithMapForEnv(tc.env)) + got := m.getLanguage() + + a.Equal(got, tc.want) + }) + } + +} + func newTestMetrics(t *testing.T, fixtures ...func(m *Metrics) error) Metrics { t.Helper() m, err := New(fixtures...) diff -Nru ubuntu-report-1.0.11/internal/metrics/metricsdata.go ubuntu-report-1.1.0/internal/metrics/metricsdata.go --- ubuntu-report-1.0.11/internal/metrics/metricsdata.go 2018-04-17 08:08:02.000000000 +0000 +++ ubuntu-report-1.1.0/internal/metrics/metricsdata.go 2018-05-25 08:43:51.000000000 +0000 @@ -27,6 +27,7 @@ Name string Type string } `json:",omitempty"` + Language string `json:",omitempty"` Timezone string `json:",omitempty"` Install json.RawMessage `json:",omitempty"` @@ -39,6 +40,7 @@ } type screenInfo struct { + Size string Resolution string Frequency string } diff -Nru ubuntu-report-1.0.11/internal/metrics/metrics.go ubuntu-report-1.1.0/internal/metrics/metrics.go --- ubuntu-report-1.0.11/internal/metrics/metrics.go 2018-04-17 08:08:02.000000000 +0000 +++ ubuntu-report-1.1.0/internal/metrics/metrics.go 2018-05-25 08:43:51.000000000 +0000 @@ -134,6 +134,7 @@ Type string }{de, sessionName, sessionType} } + r.Language = m.getLanguage() r.Timezone = m.getTimeZone() r.Install = m.installerInfo() @@ -143,6 +144,17 @@ return d, errors.Wrapf(err, "can't be converted to a valid json") } +func (m Metrics) getLanguage() string { + lang := m.getenv("LC_ALL") + if lang == "" { + lang = m.getenv("LANG") + } + if lang == "" { + lang = strings.Split(m.getenv("LANGUAGE"), ":")[0] + } + return strings.Split(lang, ".")[0] +} + func convKBToGB(s string) (float64, error) { v, err := strconv.Atoi(s) if err != nil { diff -Nru ubuntu-report-1.0.11/internal/metrics/metrics_test.go ubuntu-report-1.1.0/internal/metrics/metrics_test.go --- ubuntu-report-1.0.11/internal/metrics/metrics_test.go 2018-04-17 08:08:02.000000000 +0000 +++ ubuntu-report-1.1.0/internal/metrics/metrics_test.go 2018-05-25 08:43:51.000000000 +0000 @@ -66,7 +66,7 @@ }{ {"regular", "testdata/good", "one gpu", "one screen", "one partition", "regular", - map[string]string{"XDG_CURRENT_DESKTOP": "some:thing", "XDG_SESSION_DESKTOP": "ubuntusession", "XDG_SESSION_TYPE": "x12"}, + map[string]string{"XDG_CURRENT_DESKTOP": "some:thing", "XDG_SESSION_DESKTOP": "ubuntusession", "XDG_SESSION_TYPE": "x12", "LANG": "fr_FR.UTF-8", "LANGUAGE": "fr_FR.UTF-8"}, false}, {"empty", "testdata/none", "empty", "empty", "empty", "empty", @@ -119,7 +119,7 @@ }{ {"regular", "testdata/good", "one gpu", "one screen", "one partition", - map[string]string{"XDG_CURRENT_DESKTOP": "some:thing", "XDG_SESSION_DESKTOP": "ubuntusession", "XDG_SESSION_TYPE": "x12"}, + map[string]string{"XDG_CURRENT_DESKTOP": "some:thing", "XDG_SESSION_DESKTOP": "ubuntusession", "XDG_SESSION_TYPE": "x12", "LANG": "fr_FR.UTF-8", "LANGUAGE": "fr_FR.UTF-8"}, false}, {"empty", "testdata/none", "empty", "empty", "empty", diff -Nru ubuntu-report-1.0.11/internal/metrics/testdata/good/gold/collect ubuntu-report-1.1.0/internal/metrics/testdata/good/gold/collect --- ubuntu-report-1.0.11/internal/metrics/testdata/good/gold/collect 2018-04-17 08:08:02.000000000 +0000 +++ ubuntu-report-1.1.0/internal/metrics/testdata/good/gold/collect 2018-05-25 08:43:51.000000000 +0000 @@ -1 +1 @@ -{"Version":"18.04","OEM":{"Vendor":"DID","Product":"4287CTO"},"BIOS":{"Vendor":"DID","Version":"42 (maybe 43)"},"CPU":[{"Vendor":"Genuine","Family":"6","Model":"42","Stepping":"7"}],"Arch":"amd64","GPU":[{"Vendor":"8086","Model":"0126"}],"RAM":8,"Partitions":[159.4],"Screens":[{"Resolution":"1366x768","Frequency":"60.02"}],"Autologin":false,"LivePatch":true,"Session":{"DE":"some:thing","Name":"ubuntusession","Type":"x12"},"Timezone":"Europe/Paris","Install":{"Media":"Ubuntu 18.04 LTS \"Bionic Beaver\" - Alpha amd64 (20180305)","Type":"GTK","PartitionMethod":"use_device","DownloadUpdates":"false","Language":"fr","Minimal":"false","RestrictedAddons":"false","Stages":{"0":"language","3":"language","10":"console_setup","15":"prepare","25":"partman","27":"start_install","37":"timezone","49":"usersetup","829":"done"}},"Upgrade":{"From":"17.10","Stages":{"1337":"done"}}} \ No newline at end of file +{"Version":"18.04","OEM":{"Vendor":"DID","Product":"4287CTO"},"BIOS":{"Vendor":"DID","Version":"42 (maybe 43)"},"CPU":[{"Vendor":"Genuine","Family":"6","Model":"42","Stepping":"7"}],"Arch":"amd64","GPU":[{"Vendor":"8086","Model":"0126"}],"RAM":8,"Partitions":[159.4],"Screens":[{"Size":"277mmx156mm","Resolution":"1366x768","Frequency":"60.02"}],"Autologin":false,"LivePatch":true,"Session":{"DE":"some:thing","Name":"ubuntusession","Type":"x12"},"Language":"fr_FR","Timezone":"Europe/Paris","Install":{"Media":"Ubuntu 18.04 LTS \"Bionic Beaver\" - Alpha amd64 (20180305)","Type":"GTK","PartitionMethod":"use_device","DownloadUpdates":"false","Language":"fr","Minimal":"false","RestrictedAddons":"false","Stages":{"0":"language","3":"language","10":"console_setup","15":"prepare","25":"partman","27":"start_install","37":"timezone","49":"usersetup","829":"done"}},"Upgrade":{"From":"17.10","Stages":{"1337":"done"}}} \ No newline at end of file diff -Nru ubuntu-report-1.0.11/internal/utils/reports.go ubuntu-report-1.1.0/internal/utils/reports.go --- ubuntu-report-1.0.11/internal/utils/reports.go 2018-03-21 12:10:09.000000000 +0000 +++ ubuntu-report-1.1.0/internal/utils/reports.go 2018-05-25 08:43:51.000000000 +0000 @@ -30,6 +30,17 @@ return filepath.Join(cacheP, reportDir, distro+"."+version), nil } +// PendingReportPath of last saved pending report +func PendingReportPath(cacheP string) (string, error) { + if cacheP == "" { + var err error + if cacheP, err = cacheDir(); err != nil { + return "", err + } + } + return filepath.Join(cacheP, reportDir, "pending"), nil +} + func cacheDir() (string, error) { d := os.Getenv("XDG_CACHE_HOME") if filepath.IsAbs(d) { diff -Nru ubuntu-report-1.0.11/internal/utils/reports_test.go ubuntu-report-1.1.0/internal/utils/reports_test.go --- ubuntu-report-1.0.11/internal/utils/reports_test.go 2018-03-21 12:13:41.000000000 +0000 +++ ubuntu-report-1.1.0/internal/utils/reports_test.go 2018-05-25 08:43:51.000000000 +0000 @@ -51,6 +51,44 @@ } } +func TestPendingReportPath(t *testing.T) { + + // get current user for some tests + u, err := user.Current() + if err != nil { + t.Fatalf("couldn't get current user for testing: %v", err) + } + + testCases := []struct { + name string + home string + xdg_cache_dir string + explicitacheDir string + + want string + wantErr bool + }{ + {"regular", "/some/dir", "", "", "/some/dir/.cache/ubuntu-report/pending", false}, + {"relative xdg path", "/some/dir", "xdg_cache_path", "", "/some/dir/xdg_cache_path/ubuntu-report/pending", false}, + {"absolute xdg path", "/some/dir", "/xdg_cache_path", "", "/xdg_cache_path/ubuntu-report/pending", false}, + {"no home dir", "", "", "", u.HomeDir + "/.cache/ubuntu-report/pending", false}, + {"explicit cache dir", "", "", "/explicit/cachedir", "/explicit/cachedir/ubuntu-report/pending", false}, + {"explicit cache dir takes predecedence", "/some/dir", "/xdg_cache_path", "/explicit/cachedir", "/explicit/cachedir/ubuntu-report/pending", false}, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + defer changeEnv(t, "HOME", tc.home)() + defer changeEnv(t, "XDG_CACHE_HOME", tc.xdg_cache_dir)() + a := helper.Asserter{T: t} + + got, err := utils.PendingReportPath(tc.explicitacheDir) + + a.CheckWantedErr(err, tc.wantErr) + a.Equal(got, tc.want) + }) + } +} + func changeEnv(t *testing.T, key, value string) func() { t.Helper() orig := os.Getenv(key) diff -Nru ubuntu-report-1.0.11/pkg/sysmetrics/api.go ubuntu-report-1.1.0/pkg/sysmetrics/api.go --- ubuntu-report-1.0.11/pkg/sysmetrics/api.go 2018-04-03 08:58:21.000000000 +0000 +++ ubuntu-report-1.1.0/pkg/sysmetrics/api.go 2018-05-25 08:43:51.000000000 +0000 @@ -71,3 +71,15 @@ } return metricsCollectAndSend(m, r, alwaysReport, baseURL, "", os.Stdin, os.Stdout) } + +// SendPendingReport will try to send any pending report which didn't suceed previously due to network issues. +// It will try sending and exponentially back off until a send is successful. +func SendPendingReport(baseURL string) error { + log.Debug("try sending previous report") + + m, err := metrics.New() + if err != nil { + return errors.Wrapf(err, "couldn't create a metric collector") + } + return metricsSendPendingReport(m, baseURL, "", os.Stdin, os.Stdout) +} diff -Nru ubuntu-report-1.0.11/pkg/sysmetrics/api_test.go ubuntu-report-1.1.0/pkg/sysmetrics/api_test.go --- ubuntu-report-1.0.11/pkg/sysmetrics/api_test.go 2018-04-03 08:58:07.000000000 +0000 +++ ubuntu-report-1.1.0/pkg/sysmetrics/api_test.go 2018-05-25 08:43:51.000000000 +0000 @@ -63,10 +63,7 @@ err := sysmetrics.SendReport([]byte(fmt.Sprintf(`{ %s: "18.04" }`, sysmetrics.ExpectedReportItem)), tc.alwaysReport, ts.URL) - if err != nil { - t.Fatal("we didn't expect getting an error, got:", err) - } - + a.CheckWantedErr(err, tc.wantErr) a.Equal(serverHit, tc.shouldHitServer) p := filepath.Join(out, helper.FindInDirectory(t, "", out)) data, err := ioutil.ReadFile(p) @@ -212,7 +209,7 @@ } } -func TestSendDceclineTwice(t *testing.T) { +func TestSendDeclineTwice(t *testing.T) { // we change current path and env variable: not parallelizable tests helper.SkipIfShort(t) @@ -538,3 +535,65 @@ }) } } + +func TestSendPendingReport(t *testing.T) { + // we change current path and env variable: not parallelizable tests + helper.SkipIfShort(t) + + testCases := []struct { + name string + + shouldHitServer bool + wantErr bool + }{ + {"regular send", true, false}, + } + for _, tc := range testCases { + tc := tc // capture range variable for parallel execution + t.Run(tc.name, func(t *testing.T) { + a := helper.Asserter{T: t} + + out, tearDown := helper.TempDir(t) + defer tearDown() + defer helper.ChangeEnv("XDG_CACHE_HOME", out)() + out = filepath.Join(out, "ubuntu-report") + + pendingReportData, err := ioutil.ReadFile(filepath.Join("testdata", "good", "ubuntu-report", "pending")) + if err != nil { + t.Fatalf("couldn't open pending report file: %v", err) + } + pendingReportPath := filepath.Join(out, "pending") + if err := os.MkdirAll(out, 0700); err != nil { + t.Fatal("couldn't create parent directory of pending report", err) + } + if err := ioutil.WriteFile(pendingReportPath, pendingReportData, 0644); err != nil { + t.Fatalf("couldn't copy pending report file to cache directory: %v", err) + } + + // we don't really care where we hit for this API integration test, internal ones test it + // and we don't really control /etc/os-release version and id. + // Same for report file + serverHit := false + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + serverHit = true + })) + defer ts.Close() + + err = sysmetrics.SendPendingReport(ts.URL) + + a.CheckWantedErr(err, tc.wantErr) + a.Equal(serverHit, tc.shouldHitServer) + + if _, pendingReportErr := os.Stat(pendingReportPath); os.IsExist(pendingReportErr) { + t.Errorf("we expected the pending report to be removed and it wasn't") + } + + p := filepath.Join(out, helper.FindInDirectory(t, "", out)) + got, err := ioutil.ReadFile(p) + if err != nil { + t.Fatalf("couldn't open report file %s", out) + } + a.Equal(got, pendingReportData) + }) + } +} diff -Nru ubuntu-report-1.0.11/pkg/sysmetrics/binmocks_test.go ubuntu-report-1.1.0/pkg/sysmetrics/binmocks_test.go --- ubuntu-report-1.0.11/pkg/sysmetrics/binmocks_test.go 2018-04-17 08:09:33.000000000 +0000 +++ ubuntu-report-1.1.0/pkg/sysmetrics/binmocks_test.go 2018-05-25 08:43:51.000000000 +0000 @@ -54,11 +54,15 @@ case "multiple gpus": fmt.Println(regularOutput) fmt.Println("00:02.0 0300: 8086:0127 (rev 09)") + case "no revision number": + fmt.Println("00:02.0 0300: 8086:0126") case "no gpu": fmt.Println(`00:00.0 0600: 8086:0104 (rev 09) 00:16.0 0780: 8086:1c3a (rev 04) 00:16.3 0700: 8086:1c3d (rev 04) 00:19.0 0200: 8086:1502 (rev 04)`) + case "hexa numbers": + fmt.Println("00:02.0 0300: 8b86:a126 (rev 09)") case "empty": case "malformed gpu line": fmt.Println("00:02.0 0300: 80860127 (rev 09)") @@ -108,6 +112,11 @@ fmt.Println(`VGA-1 connected 1920x1080+0+0 (normal left inverted right x axis y axis) 510mm x 287mm 1920x1080 60.00 59.94 50.00* 60.05 60.00 50.04 1600x1200 60.00 +`) + case "no specified screen size": + fmt.Println(`VGA-1 connected 1920x1080+0+0 (normal left inverted right x axis y axis) + 1920x1080 60.00*+ + 1600x1200 60.00 + 1680x1050 59.95 `) case "no chosen resolution": fmt.Println(`VGA-1 connected 1920x1080+0+0 (normal left inverted right x axis y axis) 510mm x 287mm 1920x1080 60.00 @@ -115,7 +124,7 @@ 1680x1050 59.95 `) case "empty": case "malformed screen line": - fmt.Println(`VGA-1 connected 1920x1080+0+0 (normal left inverted right x axis y axis) 510mm x 287mm + fmt.Println(`VGA-1 connected 1920x1080+0+0 (normal left inverted right x axis y axis) 510m x 287mm 1920x108160.00*+`) case "garbage": fmt.Println(garbageOutput) diff -Nru ubuntu-report-1.0.11/pkg/sysmetrics/run.go ubuntu-report-1.1.0/pkg/sysmetrics/run.go --- ubuntu-report-1.0.11/pkg/sysmetrics/run.go 2018-03-29 08:59:47.000000000 +0000 +++ ubuntu-report-1.1.0/pkg/sysmetrics/run.go 2018-05-25 08:43:51.000000000 +0000 @@ -9,6 +9,7 @@ "os" "path/filepath" "strings" + "time" "github.com/pkg/errors" log "github.com/sirupsen/logrus" @@ -20,6 +21,10 @@ // optOutJSON is the data sent in case of Opt-Out choice const optOutJSON = `{"OptOut": true}` +var ( + initialReportTimeoutDuration = 30 * time.Second +) + func metricsCollect(m metrics.Metrics) ([]byte, error) { data, err := m.Collect() if err != nil { @@ -55,7 +60,15 @@ return errors.Wrapf(err, "report destination url is invalid") } if err := sender.Send(u, data); err != nil { - return errors.Wrapf(err, "data were not delivered successfully to metrics server") + returnErr := errors.Wrapf(err, "data were not delivered successfully to metrics server, saving for a later automated report") + p, err := utils.PendingReportPath(reportBasePath) + if err != nil { + return errors.Wrapf(err, "couldn't get where pending reported metrics should be stored on disk: %v", returnErr) + } + if err := saveMetrics(p, data); err != nil { + return errors.Wrapf(err, "couldn't save pending reported are on disk: %v", returnErr) + } + return returnErr } return saveMetrics(reportP, data) @@ -127,7 +140,7 @@ } if err := ioutil.WriteFile(p, data, 0666); err != nil { - return errors.Wrap(err, "couldn't save reported metrics on disk") + return errors.Wrap(err, "couldn't save reported or pending metrics on disk") } return nil @@ -147,3 +160,51 @@ } return p, nil } + +func metricsSendPendingReport(m metrics.Metrics, baseURL, reportBasePath string, in io.Reader, out io.Writer) error { + distro, version, err := m.GetIDS() + if err != nil { + return errors.Wrapf(err, "couldn't get mandatory information") + } + + reportP, err := utils.ReportPath(distro, version, reportBasePath) + if err != nil { + return errors.Wrapf(err, "couldn't get where to save reported metrics on disk") + } + + pending, err := utils.PendingReportPath(reportBasePath) + if err != nil { + return errors.Wrapf(err, "couldn't get where to previous reported metrics are on disk") + } + data, err := ioutil.ReadFile(pending) + if err != nil { + return errors.Wrapf(err, "no pending report found") + } + + if baseURL == "" { + baseURL = sender.BaseURL + } + u, err := sender.GetURL(baseURL, distro, version) + if err != nil { + return errors.Wrapf(err, "report destination url is invalid") + } + + wait := time.Duration(initialReportTimeoutDuration) + for { + if err := sender.Send(u, data); err != nil { + log.Errorf("data were not delivered successfully to metrics server, retrying in %ds", wait/(1000*1000*1000)) + time.Sleep(wait) + wait = wait * 2 + if wait > time.Duration(30*time.Minute) { + wait = time.Duration(30 * time.Minute) + } + continue + } + break + } + + if err := os.Remove(pending); err != nil { + return errors.Wrapf(err, "couldn't remove pending report after a successful report") + } + return saveMetrics(reportP, data) +} diff -Nru ubuntu-report-1.0.11/pkg/sysmetrics/run_test.go ubuntu-report-1.1.0/pkg/sysmetrics/run_test.go --- ubuntu-report-1.0.11/pkg/sysmetrics/run_test.go 2018-04-17 08:18:45.000000000 +0000 +++ ubuntu-report-1.1.0/pkg/sysmetrics/run_test.go 2018-05-25 08:43:51.000000000 +0000 @@ -99,28 +99,29 @@ manualServerURL string cacheReportP string + pendingReportP string shouldHitServer bool sHitHat string wantErr bool }{ {"send data", "testdata/good", []byte(`{ "some-data": true }`), true, "", - "ubuntu-report/ubuntu.18.04", true, "/ubuntu/desktop/18.04", false}, + "ubuntu-report/ubuntu.18.04", "", true, "/ubuntu/desktop/18.04", false}, {"nack send data", "testdata/good", []byte(`{ "some-data": true }`), false, "", - "ubuntu-report/ubuntu.18.04", true, "/ubuntu/desktop/18.04", false}, + "ubuntu-report/ubuntu.18.04", "", true, "/ubuntu/desktop/18.04", false}, {"no IDs (mandatory)", "testdata/no-ids", []byte(`{ "some-data": true }`), true, "", - "ubuntu-report", false, "", true}, - {"other URL", - "testdata/good", []byte(`{ "some-data": true }`), true, "localhost:4299", - "ubuntu-report", false, "", true}, + "ubuntu-report", "", false, "", true}, + {"no network", + "testdata/good", []byte(`{ "some-data": true }`), true, "http://localhost:4299", + "ubuntu-report", "ubuntu-report/pending", false, "", true}, {"invalid URL", "testdata/good", []byte(`{ "some-data": true }`), true, "http://a b.com/", - "ubuntu-report", false, "", true}, + "ubuntu-report", "", false, "", true}, {"unwritable path", "testdata/good", []byte(`{ "some-data": true }`), true, "", - "/unwritable/cache/path", true, "/ubuntu/desktop/18.04", true}, + "/unwritable/cache/path", "", true, "/ubuntu/desktop/18.04", true}, } for _, tc := range testCases { tc := tc // capture range variable for parallel execution @@ -156,8 +157,21 @@ if tc.shouldHitServer && serverHitAt == "" { t.Error("we should have hit the local server and it didn't") } - if _, err := os.Stat(filepath.Join(out, tc.cacheReportP)); !os.IsNotExist(err) { - t.Errorf("we didn't expect finding a cache report path as we erroring out") + if tc.pendingReportP == "" { + if _, err := os.Stat(filepath.Join(out, tc.cacheReportP)); !os.IsNotExist(err) { + t.Errorf("we didn't expect finding a cache report path as we erroring out") + } + } else { + gotF, err := os.Open(filepath.Join(out, tc.pendingReportP)) + if err != nil { + t.Fatal("didn't generate a pending report file on disk", err) + } + got, err := ioutil.ReadAll(gotF) + if err != nil { + t.Fatal("couldn't read generated pending report file", err) + } + want := helper.LoadOrUpdateGolden(t, filepath.Join(tc.root, "gold", fmt.Sprintf("metricssendpending.%s.%t", strings.Replace(tc.name, " ", "_", -1), tc.ack)), got, *Update) + a.Equal(got, want) } return } @@ -258,28 +272,29 @@ manualServerURL string cacheReportP string + pendingReportP string shouldHitServer bool sHitHat string wantErr bool }{ {"regular report auto", "testdata/good", "one gpu", "one screen", "one partition", "regular", - map[string]string{"XDG_CURRENT_DESKTOP": "some:thing", "XDG_SESSION_DESKTOP": "ubuntusession", "XDG_SESSION_TYPE": "x12"}, + map[string]string{"XDG_CURRENT_DESKTOP": "some:thing", "XDG_SESSION_DESKTOP": "ubuntusession", "XDG_SESSION_TYPE": "x12", "LANG": "fr_FR.UTF-8", "LANGUAGE": "fr_FR.UTF-8"}, ReportAuto, "", - "ubuntu-report/ubuntu.18.04", true, "/ubuntu/desktop/18.04", false}, + "ubuntu-report/ubuntu.18.04", "", true, "/ubuntu/desktop/18.04", false}, {"regular report OptOut", "testdata/good", "one gpu", "one screen", "one partition", "regular", - map[string]string{"XDG_CURRENT_DESKTOP": "some:thing", "XDG_SESSION_DESKTOP": "ubuntusession", "XDG_SESSION_TYPE": "x12"}, + map[string]string{"XDG_CURRENT_DESKTOP": "some:thing", "XDG_SESSION_DESKTOP": "ubuntusession", "XDG_SESSION_TYPE": "x12", "LANG": "fr_FR.UTF-8", "LANGUAGE": "fr_FR.UTF-8"}, ReportOptOut, "", - "ubuntu-report/ubuntu.18.04", true, "/ubuntu/desktop/18.04", false}, + "ubuntu-report/ubuntu.18.04", "", true, "/ubuntu/desktop/18.04", false}, + {"no network", + "testdata/good", "", "", "", "", nil, ReportAuto, "http://localhost:4299", "ubuntu-report", "ubuntu-report/pending", false, "", true}, {"No IDs (mandatory)", - "testdata/no-ids", "", "", "", "", nil, ReportAuto, "", "ubuntu-report", false, "", true}, - {"Other URL", - "testdata/good", "", "", "", "", nil, ReportAuto, "localhost:4299", "ubuntu-report", false, "", true}, + "testdata/no-ids", "", "", "", "", nil, ReportAuto, "", "ubuntu-report", "", false, "", true}, {"Invalid URL", - "testdata/good", "", "", "", "", nil, ReportAuto, "http://a b.com/", "ubuntu-report", false, "", true}, + "testdata/good", "", "", "", "", nil, ReportAuto, "http://a b.com/", "ubuntu-report", "", false, "", true}, {"Unwritable path", - "testdata/good", "", "", "", "", nil, ReportAuto, "", "/unwritable/cache/path", true, "/ubuntu/desktop/18.04", true}, + "testdata/good", "", "", "", "", nil, ReportAuto, "", "/unwritable/cache/path", "", true, "/ubuntu/desktop/18.04", true}, } for _, tc := range testCases { tc := tc // capture range variable for parallel execution @@ -320,8 +335,21 @@ if tc.shouldHitServer && serverHitAt == "" { t.Error("we should have hit the local server and it didn't") } - if _, err := os.Stat(filepath.Join(out, tc.cacheReportP)); !os.IsNotExist(err) { - t.Errorf("we didn't expect finding a cache report path as we erroring out") + if tc.pendingReportP == "" { + if _, err := os.Stat(filepath.Join(out, tc.cacheReportP)); !os.IsNotExist(err) { + t.Errorf("we didn't expect finding a cache report path as we erroring out") + } + } else { + gotF, err := os.Open(filepath.Join(out, tc.pendingReportP)) + if err != nil { + t.Fatal("didn't generate a pending report file on disk", err) + } + got, err := ioutil.ReadAll(gotF) + if err != nil { + t.Fatal("couldn't read generated pending report file", err) + } + want := helper.LoadOrUpdateGolden(t, filepath.Join(tc.root, "gold", fmt.Sprintf("pendingreport.ReportType%d", int(tc.r))), got, *Update) + a.Equal(got, want) } return } @@ -363,7 +391,7 @@ m, cancelGPU, cancelScreen, cancelPartition, cancelArchitecture := newTestMetricsWithCommands(t, "testdata/good", "one gpu", "one screen", "one partition", "regular", - map[string]string{"XDG_CURRENT_DESKTOP": "some:thing", "XDG_SESSION_DESKTOP": "ubuntusession", "XDG_SESSION_TYPE": "x12"}) + map[string]string{"XDG_CURRENT_DESKTOP": "some:thing", "XDG_SESSION_DESKTOP": "ubuntusession", "XDG_SESSION_TYPE": "x12", "LANG": "fr_FR.UTF-8", "LANGUAGE": "fr_FR.UTF-8"}) defer cancelGPU() defer cancelScreen() defer cancelPartition() @@ -385,7 +413,7 @@ serverHitAt = "" m, cancelGPU, cancelScreen, cancelPartition, cancelArchitecture = newTestMetricsWithCommands(t, "testdata/good", "one gpu", "one screen", "one partition", "regular", - map[string]string{"XDG_CURRENT_DESKTOP": "some:thing", "XDG_SESSION_DESKTOP": "ubuntusession", "XDG_SESSION_TYPE": "x12"}) + map[string]string{"XDG_CURRENT_DESKTOP": "some:thing", "XDG_SESSION_DESKTOP": "ubuntusession", "XDG_SESSION_TYPE": "x12", "LANG": "fr_FR.UTF-8", "LANGUAGE": "fr_FR.UTF-8"}) defer cancelGPU() defer cancelScreen() defer cancelPartition() @@ -452,7 +480,7 @@ m, cancelGPU, cancelScreen, cancelPartition, cancelArchitecture := newTestMetricsWithCommands(t, "testdata/good", "one gpu", "one screen", "one partition", "regular", - map[string]string{"XDG_CURRENT_DESKTOP": "some:thing", "XDG_SESSION_DESKTOP": "ubuntusession", "XDG_SESSION_TYPE": "x12"}) + map[string]string{"XDG_CURRENT_DESKTOP": "some:thing", "XDG_SESSION_DESKTOP": "ubuntusession", "XDG_SESSION_TYPE": "x12", "LANG": "fr_FR.UTF-8", "LANGUAGE": "fr_FR.UTF-8"}) defer cancelGPU() defer cancelScreen() defer cancelPartition() @@ -527,6 +555,136 @@ }) } } + +func TestMetricsSendPendingReport(t *testing.T) { + t.Parallel() + initialReportTimeoutDuration = 0 + + testCases := []struct { + name string + root string + manualServerURL string + + cacheReportP string + pendingReportP string + pendingReportKept bool + numHitServer int + sHitHat string + wantErr bool + }{ + {"send previous report", + "testdata/good", "", + "ubuntu-report/ubuntu.18.04", "ubuntu-report/pending", false, 1, "/ubuntu/desktop/18.04", false}, + {"no previous report", + "testdata/good", "", + "", "", false, 0, "", true}, + {"send previous report after backoff", + "testdata/good", "", + "ubuntu-report/ubuntu.18.04", "ubuntu-report/pending", false, 2, "/ubuntu/desktop/18.04", false}, + {"no IDs (mandatory)", + "testdata/no-ids", "", + "", "", false, 0, "", true}, + {"invalid URL", + "testdata/good", "http://a b.com/", + "", "", false, 0, "", true}, + {"unwritable path", + "testdata/good", "", + "", "ubuntu-report/pending", true, 1, "/ubuntu/desktop/18.04", true}, + } + for _, tc := range testCases { + tc := tc // capture range variable for parallel execution + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + a := helper.Asserter{T: t} + + m := metrics.NewTestMetrics(tc.root, nil, nil, nil, nil, os.Getenv) + out, tearDown := helper.TempDir(t) + defer tearDown() + if strings.HasPrefix(tc.cacheReportP, "/") { + // absolute path, override temporary one + out = tc.cacheReportP + } + var pendingReportData []byte + var err error + resetwritable := func() {} + if tc.pendingReportP != "" { + if pendingReportData, err = ioutil.ReadFile(filepath.Join(tc.root, tc.pendingReportP)); err != nil { + t.Fatalf("couldn't open pending report file: %v", err) + } + tc.pendingReportP = filepath.Join(out, tc.pendingReportP) + d := filepath.Dir(tc.pendingReportP) + if err := os.MkdirAll(d, 0700); err != nil { + t.Fatal("couldn't create parent directory of pending report", err) + } + if err := ioutil.WriteFile(tc.pendingReportP, pendingReportData, 0644); err != nil { + t.Fatalf("couldn't copy pending report file to cache directory: %v", err) + } + // switch back mode to unwritable + if strings.HasPrefix(tc.name, "unwritable") { + if err := os.Chmod(d, 0500); err != nil { + t.Fatalf("couldn't switch %s to not being writable: %v", d, err) + } + resetwritable = func() { + if err := os.Chmod(d, 0700); err != nil { + t.Fatalf("couldn't switch %s back to being writable: %v", d, err) + } + } + defer resetwritable() + } + } + + serverHitAt := "" + numHitServer := 0 + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + numHitServer++ + if numHitServer < tc.numHitServer { + http.NotFound(w, r) + return + } + serverHitAt = r.URL.String() + })) + defer ts.Close() + url := tc.manualServerURL + if url == "" { + url = ts.URL + } + + err = metricsSendPendingReport(m, url, out, os.Stdout, os.Stdin) + + // restore directory state for checking + resetwritable() + + a.CheckWantedErr(err, tc.wantErr) + a.Equal(numHitServer, tc.numHitServer) + a.Equal(serverHitAt, tc.sHitHat) + + _, pendingReportErr := os.Stat(tc.pendingReportP) + if !tc.pendingReportKept && os.IsExist(pendingReportErr) { + t.Errorf("we expected the pending report to be removed and it wasn't") + } else if tc.pendingReportKept && os.IsNotExist(pendingReportErr) { + t.Errorf("we expected the pending report to be kept and it was removed") + } + + // check we didn't do too much work on error + if err != nil { + if _, err := os.Stat(filepath.Join(out, tc.cacheReportP)); os.IsExist(err) { + t.Errorf("we didn't expect finding a cache report path as we erroring out") + } + return + } + + gotF, err := os.Open(filepath.Join(out, tc.cacheReportP)) + if err != nil { + t.Fatal("didn't generate a report file on disk", err) + } + got, err := ioutil.ReadAll(gotF) + if err != nil { + t.Fatal("couldn't read generated report file", err) + } + a.Equal(got, pendingReportData) + }) + } +} func newMockShortCmd(t *testing.T, s ...string) (*exec.Cmd, context.CancelFunc) { t.Helper() diff -Nru ubuntu-report-1.0.11/pkg/sysmetrics/testdata/good/gold/cachereport.ReportType1 ubuntu-report-1.1.0/pkg/sysmetrics/testdata/good/gold/cachereport.ReportType1 --- ubuntu-report-1.0.11/pkg/sysmetrics/testdata/good/gold/cachereport.ReportType1 2018-04-17 08:19:09.000000000 +0000 +++ ubuntu-report-1.1.0/pkg/sysmetrics/testdata/good/gold/cachereport.ReportType1 2018-05-25 08:43:51.000000000 +0000 @@ -29,6 +29,7 @@ ], "Screens": [ { + "Size": "277mmx156mm", "Resolution": "1366x768", "Frequency": "60.02" } @@ -40,6 +41,7 @@ "Name": "ubuntusession", "Type": "x12" }, + "Language": "fr_FR", "Timezone": "Europe/Paris", "Install": { "Media": "Ubuntu 18.04 LTS \"Bionic Beaver\" - Alpha amd64 (20180305)", diff -Nru ubuntu-report-1.0.11/pkg/sysmetrics/testdata/good/gold/cachereport-twice.ReportType0-y ubuntu-report-1.1.0/pkg/sysmetrics/testdata/good/gold/cachereport-twice.ReportType0-y --- ubuntu-report-1.0.11/pkg/sysmetrics/testdata/good/gold/cachereport-twice.ReportType0-y 2018-04-17 08:19:09.000000000 +0000 +++ ubuntu-report-1.1.0/pkg/sysmetrics/testdata/good/gold/cachereport-twice.ReportType0-y 2018-05-25 08:43:51.000000000 +0000 @@ -29,6 +29,7 @@ ], "Screens": [ { + "Size": "277mmx156mm", "Resolution": "1366x768", "Frequency": "60.02" } @@ -40,6 +41,7 @@ "Name": "ubuntusession", "Type": "x12" }, + "Language": "fr_FR", "Timezone": "Europe/Paris", "Install": { "Media": "Ubuntu 18.04 LTS \"Bionic Beaver\" - Alpha amd64 (20180305)", diff -Nru ubuntu-report-1.0.11/pkg/sysmetrics/testdata/good/gold/cachereport-twice.ReportType0-Y ubuntu-report-1.1.0/pkg/sysmetrics/testdata/good/gold/cachereport-twice.ReportType0-Y --- ubuntu-report-1.0.11/pkg/sysmetrics/testdata/good/gold/cachereport-twice.ReportType0-Y 2018-04-17 08:19:09.000000000 +0000 +++ ubuntu-report-1.1.0/pkg/sysmetrics/testdata/good/gold/cachereport-twice.ReportType0-Y 2018-05-25 08:43:51.000000000 +0000 @@ -29,6 +29,7 @@ ], "Screens": [ { + "Size": "277mmx156mm", "Resolution": "1366x768", "Frequency": "60.02" } @@ -40,6 +41,7 @@ "Name": "ubuntusession", "Type": "x12" }, + "Language": "fr_FR", "Timezone": "Europe/Paris", "Install": { "Media": "Ubuntu 18.04 LTS \"Bionic Beaver\" - Alpha amd64 (20180305)", diff -Nru ubuntu-report-1.0.11/pkg/sysmetrics/testdata/good/gold/cachereport-twice.ReportType0-yes ubuntu-report-1.1.0/pkg/sysmetrics/testdata/good/gold/cachereport-twice.ReportType0-yes --- ubuntu-report-1.0.11/pkg/sysmetrics/testdata/good/gold/cachereport-twice.ReportType0-yes 2018-04-17 08:19:09.000000000 +0000 +++ ubuntu-report-1.1.0/pkg/sysmetrics/testdata/good/gold/cachereport-twice.ReportType0-yes 2018-05-25 08:43:51.000000000 +0000 @@ -29,6 +29,7 @@ ], "Screens": [ { + "Size": "277mmx156mm", "Resolution": "1366x768", "Frequency": "60.02" } @@ -40,6 +41,7 @@ "Name": "ubuntusession", "Type": "x12" }, + "Language": "fr_FR", "Timezone": "Europe/Paris", "Install": { "Media": "Ubuntu 18.04 LTS \"Bionic Beaver\" - Alpha amd64 (20180305)", diff -Nru ubuntu-report-1.0.11/pkg/sysmetrics/testdata/good/gold/cachereport-twice.ReportType0-YES ubuntu-report-1.1.0/pkg/sysmetrics/testdata/good/gold/cachereport-twice.ReportType0-YES --- ubuntu-report-1.0.11/pkg/sysmetrics/testdata/good/gold/cachereport-twice.ReportType0-YES 2018-04-17 08:19:09.000000000 +0000 +++ ubuntu-report-1.1.0/pkg/sysmetrics/testdata/good/gold/cachereport-twice.ReportType0-YES 2018-05-25 08:43:51.000000000 +0000 @@ -29,6 +29,7 @@ ], "Screens": [ { + "Size": "277mmx156mm", "Resolution": "1366x768", "Frequency": "60.02" } @@ -40,6 +41,7 @@ "Name": "ubuntusession", "Type": "x12" }, + "Language": "fr_FR", "Timezone": "Europe/Paris", "Install": { "Media": "Ubuntu 18.04 LTS \"Bionic Beaver\" - Alpha amd64 (20180305)", diff -Nru ubuntu-report-1.0.11/pkg/sysmetrics/testdata/good/gold/cachereport-twice.ReportType1 ubuntu-report-1.1.0/pkg/sysmetrics/testdata/good/gold/cachereport-twice.ReportType1 --- ubuntu-report-1.0.11/pkg/sysmetrics/testdata/good/gold/cachereport-twice.ReportType1 2018-04-17 08:19:09.000000000 +0000 +++ ubuntu-report-1.1.0/pkg/sysmetrics/testdata/good/gold/cachereport-twice.ReportType1 2018-05-25 08:43:51.000000000 +0000 @@ -29,6 +29,7 @@ ], "Screens": [ { + "Size": "277mmx156mm", "Resolution": "1366x768", "Frequency": "60.02" } @@ -40,6 +41,7 @@ "Name": "ubuntusession", "Type": "x12" }, + "Language": "fr_FR", "Timezone": "Europe/Paris", "Install": { "Media": "Ubuntu 18.04 LTS \"Bionic Beaver\" - Alpha amd64 (20180305)", diff -Nru ubuntu-report-1.0.11/pkg/sysmetrics/testdata/good/gold/metricscollect ubuntu-report-1.1.0/pkg/sysmetrics/testdata/good/gold/metricscollect --- ubuntu-report-1.0.11/pkg/sysmetrics/testdata/good/gold/metricscollect 2018-04-17 08:19:08.000000000 +0000 +++ ubuntu-report-1.1.0/pkg/sysmetrics/testdata/good/gold/metricscollect 2018-05-25 08:43:51.000000000 +0000 @@ -29,6 +29,7 @@ ], "Screens": [ { + "Size": "277mmx156mm", "Resolution": "1366x768", "Frequency": "60.02" } diff -Nru ubuntu-report-1.0.11/pkg/sysmetrics/testdata/good/gold/metricssendpending.no_network.true ubuntu-report-1.1.0/pkg/sysmetrics/testdata/good/gold/metricssendpending.no_network.true --- ubuntu-report-1.0.11/pkg/sysmetrics/testdata/good/gold/metricssendpending.no_network.true 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-report-1.1.0/pkg/sysmetrics/testdata/good/gold/metricssendpending.no_network.true 2018-05-25 08:43:51.000000000 +0000 @@ -0,0 +1 @@ +{ "some-data": true } \ No newline at end of file diff -Nru ubuntu-report-1.0.11/pkg/sysmetrics/testdata/good/gold/pendingreport.ReportType1 ubuntu-report-1.1.0/pkg/sysmetrics/testdata/good/gold/pendingreport.ReportType1 --- ubuntu-report-1.0.11/pkg/sysmetrics/testdata/good/gold/pendingreport.ReportType1 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-report-1.1.0/pkg/sysmetrics/testdata/good/gold/pendingreport.ReportType1 2018-05-25 08:43:51.000000000 +0000 @@ -0,0 +1,49 @@ +{ + "Version": "18.04", + "OEM": { + "Vendor": "DID", + "Product": "4287CTO" + }, + "BIOS": { + "Vendor": "DID", + "Version": "42 (maybe 43)" + }, + "CPU": [ + { + "Vendor": "Genuine", + "Family": "6", + "Model": "42", + "Stepping": "7" + } + ], + "RAM": 8, + "Autologin": false, + "LivePatch": true, + "Timezone": "Europe/Paris", + "Install": { + "Media": "Ubuntu 18.04 LTS \"Bionic Beaver\" - Alpha amd64 (20180305)", + "Type": "GTK", + "PartitionMethod": "use_device", + "DownloadUpdates": "false", + "Language": "fr", + "Minimal": "false", + "RestrictedAddons": "false", + "Stages": { + "0": "language", + "3": "language", + "10": "console_setup", + "15": "prepare", + "25": "partman", + "27": "start_install", + "37": "timezone", + "49": "usersetup", + "829": "done" + } + }, + "Upgrade": { + "From": "17.10", + "Stages": { + "1337": "done" + } + } +} \ No newline at end of file diff -Nru ubuntu-report-1.0.11/pkg/sysmetrics/testdata/good/ubuntu-report/pending ubuntu-report-1.1.0/pkg/sysmetrics/testdata/good/ubuntu-report/pending --- ubuntu-report-1.0.11/pkg/sysmetrics/testdata/good/ubuntu-report/pending 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-report-1.1.0/pkg/sysmetrics/testdata/good/ubuntu-report/pending 2018-05-25 08:43:51.000000000 +0000 @@ -0,0 +1,4 @@ +{ + "Version": "foo", + "SomeData": true +} diff -Nru ubuntu-report-1.0.11/pkg/sysmetrics/testdata/missing/pendingreport/etc/gdm3/custom.conf ubuntu-report-1.1.0/pkg/sysmetrics/testdata/missing/pendingreport/etc/gdm3/custom.conf --- ubuntu-report-1.0.11/pkg/sysmetrics/testdata/missing/pendingreport/etc/gdm3/custom.conf 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-report-1.1.0/pkg/sysmetrics/testdata/missing/pendingreport/etc/gdm3/custom.conf 2018-05-25 08:43:51.000000000 +0000 @@ -0,0 +1,29 @@ +# GDM configuration storage +# +# See /usr/share/gdm/gdm.schemas for a list of available options. + +[daemon] +# Uncoment the line below to force the login screen to use Xorg +#WaylandEnable=false + +# Enabling automatic login +# AutomaticLoginEnable = true +# AutomaticLogin = user1 + +# Enabling timed login +# TimedLoginEnable = true +# TimedLogin = user1 +# TimedLoginDelay = 10 + +[security] + +[xdmcp] + +[chooser] + +[debug] +# Uncomment the line below to turn on debugging +# More verbose logs +# Additionally lets the X server dump core if it crashes +Enable=true + diff -Nru ubuntu-report-1.0.11/pkg/sysmetrics/testdata/missing/pendingreport/etc/os-release ubuntu-report-1.1.0/pkg/sysmetrics/testdata/missing/pendingreport/etc/os-release --- ubuntu-report-1.0.11/pkg/sysmetrics/testdata/missing/pendingreport/etc/os-release 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-report-1.1.0/pkg/sysmetrics/testdata/missing/pendingreport/etc/os-release 2018-05-25 08:43:51.000000000 +0000 @@ -0,0 +1,12 @@ +NAME="Ubuntu" +VERSION="18.04 LTS (Bionic Beaver)" +ID=ubuntu +ID_LIKE=debian +PRETTY_NAME="Ubuntu Bionic Beaver (development branch)" +VERSION_ID="18.04" +HOME_URL="https://www.ubuntu.com/" +SUPPORT_URL="https://help.ubuntu.com/" +BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/" +PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy" +VERSION_CODENAME=bionic +UBUNTU_CODENAME=bionic diff -Nru ubuntu-report-1.0.11/pkg/sysmetrics/testdata/missing/pendingreport/etc/timezone ubuntu-report-1.1.0/pkg/sysmetrics/testdata/missing/pendingreport/etc/timezone --- ubuntu-report-1.0.11/pkg/sysmetrics/testdata/missing/pendingreport/etc/timezone 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-report-1.1.0/pkg/sysmetrics/testdata/missing/pendingreport/etc/timezone 2018-05-25 08:43:51.000000000 +0000 @@ -0,0 +1 @@ +Europe/Paris diff -Nru ubuntu-report-1.0.11/pkg/sysmetrics/testdata/missing/pendingreport/proc/cpuinfo ubuntu-report-1.1.0/pkg/sysmetrics/testdata/missing/pendingreport/proc/cpuinfo --- ubuntu-report-1.0.11/pkg/sysmetrics/testdata/missing/pendingreport/proc/cpuinfo 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-report-1.1.0/pkg/sysmetrics/testdata/missing/pendingreport/proc/cpuinfo 2018-05-25 08:43:51.000000000 +0000 @@ -0,0 +1,108 @@ +processor : 0 +vendor_id : Genuine +cpu family : 6 +model : 42 +model name : Vendor(R) Core(TM) i7-2640M CPU @ 2.80GHz +stepping : 7 +microcode : 0x2d +cpu MHz : 2784.701 +cache size : 4096 KB +physical id : 0 +siblings : 4 +core id : 0 +cpu cores : 2 +apicid : 0 +initial apicid : 0 +fpu : yes +fpu_exception : yes +cpuid level : 13 +wp : yes +flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm epb pti tpr_shadow vnmi flexpriority ept vpid xsaveopt ibpb ibrs stibp dtherm ida arat pln pts +bugs : cpu_meltdown spectre_v1 spectre_v2 +bogomips : 5581.74 +clflush size : 64 +cache_alignment : 64 +address sizes : 36 bits physical, 48 bits virtual +power management: + +processor : 1 +vendor_id : Genuine +cpu family : 6 +model : 42 +model name : Vendor(R) Core(TM) i7-2640M CPU @ 2.80GHz +stepping : 7 +microcode : 0x2d +cpu MHz : 2850.406 +cache size : 4096 KB +physical id : 0 +siblings : 4 +core id : 0 +cpu cores : 2 +apicid : 1 +initial apicid : 1 +fpu : yes +fpu_exception : yes +cpuid level : 13 +wp : yes +flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm epb pti tpr_shadow vnmi flexpriority ept vpid xsaveopt ibpb ibrs stibp dtherm ida arat pln pts +bugs : cpu_meltdown spectre_v1 spectre_v2 +bogomips : 5581.74 +clflush size : 64 +cache_alignment : 64 +address sizes : 36 bits physical, 48 bits virtual +power management: + +processor : 2 +vendor_id : Genuine +cpu family : 6 +model : 42 +model name : Vendor(R) Core(TM) i7-2640M CPU @ 2.80GHz +stepping : 7 +microcode : 0x2d +cpu MHz : 3264.009 +cache size : 4096 KB +physical id : 0 +siblings : 4 +core id : 1 +cpu cores : 2 +apicid : 2 +initial apicid : 2 +fpu : yes +fpu_exception : yes +cpuid level : 13 +wp : yes +flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm epb pti tpr_shadow vnmi flexpriority ept vpid xsaveopt ibpb ibrs stibp dtherm ida arat pln pts +bugs : cpu_meltdown spectre_v1 spectre_v2 +bogomips : 5581.74 +clflush size : 64 +cache_alignment : 64 +address sizes : 36 bits physical, 48 bits virtual +power management: + +processor : 3 +vendor_id : Genuine +cpu family : 6 +model : 42 +model name : Vendor(R) Core(TM) i7-2640M CPU @ 2.80GHz +stepping : 7 +microcode : 0x2d +cpu MHz : 3279.776 +cache size : 4096 KB +physical id : 0 +siblings : 4 +core id : 1 +cpu cores : 2 +apicid : 3 +initial apicid : 3 +fpu : yes +fpu_exception : yes +cpuid level : 13 +wp : yes +flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm epb pti tpr_shadow vnmi flexpriority ept vpid xsaveopt ibpb ibrs stibp dtherm ida arat pln pts +bugs : cpu_meltdown spectre_v1 spectre_v2 +bogomips : 5581.74 +clflush size : 64 +cache_alignment : 64 +address sizes : 36 bits physical, 48 bits virtual +power management: + diff -Nru ubuntu-report-1.0.11/pkg/sysmetrics/testdata/missing/pendingreport/proc/meminfo ubuntu-report-1.1.0/pkg/sysmetrics/testdata/missing/pendingreport/proc/meminfo --- ubuntu-report-1.0.11/pkg/sysmetrics/testdata/missing/pendingreport/proc/meminfo 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-report-1.1.0/pkg/sysmetrics/testdata/missing/pendingreport/proc/meminfo 2018-05-25 08:43:51.000000000 +0000 @@ -0,0 +1,47 @@ +MemTotal: 8048100 kB +MemFree: 264296 kB +MemAvailable: 1094916 kB +Buffers: 92476 kB +Cached: 1764640 kB +SwapCached: 3096 kB +Active: 5984340 kB +Inactive: 1093316 kB +Active(anon): 5345756 kB +Inactive(anon): 810500 kB +Active(file): 638584 kB +Inactive(file): 282816 kB +Unevictable: 872 kB +Mlocked: 872 kB +SwapTotal: 8266748 kB +SwapFree: 7784444 kB +Dirty: 560 kB +Writeback: 0 kB +AnonPages: 5220400 kB +Mapped: 971772 kB +Shmem: 979704 kB +Slab: 372044 kB +SReclaimable: 212500 kB +SUnreclaim: 159544 kB +KernelStack: 37888 kB +PageTables: 139132 kB +NFS_Unstable: 0 kB +Bounce: 0 kB +WritebackTmp: 0 kB +CommitLimit: 12290796 kB +Committed_AS: 29182916 kB +VmallocTotal: 34359738367 kB +VmallocUsed: 0 kB +VmallocChunk: 0 kB +HardwareCorrupted: 0 kB +AnonHugePages: 0 kB +ShmemHugePages: 0 kB +ShmemPmdMapped: 0 kB +CmaTotal: 0 kB +CmaFree: 0 kB +HugePages_Total: 0 +HugePages_Free: 0 +HugePages_Rsvd: 0 +HugePages_Surp: 0 +Hugepagesize: 2048 kB +DirectMap4k: 573056 kB +DirectMap2M: 7696384 kB diff -Nru ubuntu-report-1.0.11/pkg/sysmetrics/testdata/missing/pendingreport/sys/class/dmi/id/bios_vendor ubuntu-report-1.1.0/pkg/sysmetrics/testdata/missing/pendingreport/sys/class/dmi/id/bios_vendor --- ubuntu-report-1.0.11/pkg/sysmetrics/testdata/missing/pendingreport/sys/class/dmi/id/bios_vendor 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-report-1.1.0/pkg/sysmetrics/testdata/missing/pendingreport/sys/class/dmi/id/bios_vendor 2018-05-25 08:43:51.000000000 +0000 @@ -0,0 +1 @@ +DID diff -Nru ubuntu-report-1.0.11/pkg/sysmetrics/testdata/missing/pendingreport/sys/class/dmi/id/bios_version ubuntu-report-1.1.0/pkg/sysmetrics/testdata/missing/pendingreport/sys/class/dmi/id/bios_version --- ubuntu-report-1.0.11/pkg/sysmetrics/testdata/missing/pendingreport/sys/class/dmi/id/bios_version 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-report-1.1.0/pkg/sysmetrics/testdata/missing/pendingreport/sys/class/dmi/id/bios_version 2018-05-25 08:43:51.000000000 +0000 @@ -0,0 +1 @@ +42 (maybe 43) diff -Nru ubuntu-report-1.0.11/pkg/sysmetrics/testdata/missing/pendingreport/sys/class/dmi/id/product_name ubuntu-report-1.1.0/pkg/sysmetrics/testdata/missing/pendingreport/sys/class/dmi/id/product_name --- ubuntu-report-1.0.11/pkg/sysmetrics/testdata/missing/pendingreport/sys/class/dmi/id/product_name 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-report-1.1.0/pkg/sysmetrics/testdata/missing/pendingreport/sys/class/dmi/id/product_name 2018-05-25 08:43:51.000000000 +0000 @@ -0,0 +1 @@ +4287CTO diff -Nru ubuntu-report-1.0.11/pkg/sysmetrics/testdata/missing/pendingreport/sys/class/dmi/id/sys_vendor ubuntu-report-1.1.0/pkg/sysmetrics/testdata/missing/pendingreport/sys/class/dmi/id/sys_vendor --- ubuntu-report-1.0.11/pkg/sysmetrics/testdata/missing/pendingreport/sys/class/dmi/id/sys_vendor 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-report-1.1.0/pkg/sysmetrics/testdata/missing/pendingreport/sys/class/dmi/id/sys_vendor 2018-05-25 08:43:51.000000000 +0000 @@ -0,0 +1 @@ +DID diff -Nru ubuntu-report-1.0.11/pkg/sysmetrics/testdata/missing/pendingreport/var/log/installer/telemetry ubuntu-report-1.1.0/pkg/sysmetrics/testdata/missing/pendingreport/var/log/installer/telemetry --- ubuntu-report-1.0.11/pkg/sysmetrics/testdata/missing/pendingreport/var/log/installer/telemetry 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-report-1.1.0/pkg/sysmetrics/testdata/missing/pendingreport/var/log/installer/telemetry 2018-05-25 08:43:51.000000000 +0000 @@ -0,0 +1 @@ +{"Media": "Ubuntu 18.04 LTS \"Bionic Beaver\" - Alpha amd64 (20180305)", "Type": "GTK", "PartitionMethod": "use_device", "DownloadUpdates": "false", "Language": "fr", "Minimal": "false", "RestrictedAddons": "false", "Stages": {"0": "language", "3": "language", "10": "console_setup", "15": "prepare", "25": "partman", "27": "start_install", "37": "timezone", "49": "usersetup", "829": "done"}} diff -Nru ubuntu-report-1.0.11/pkg/sysmetrics/testdata/missing/pendingreport/var/log/upgrade/telemetry ubuntu-report-1.1.0/pkg/sysmetrics/testdata/missing/pendingreport/var/log/upgrade/telemetry --- ubuntu-report-1.0.11/pkg/sysmetrics/testdata/missing/pendingreport/var/log/upgrade/telemetry 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-report-1.1.0/pkg/sysmetrics/testdata/missing/pendingreport/var/log/upgrade/telemetry 2018-05-25 08:43:51.000000000 +0000 @@ -0,0 +1 @@ +{"From": "17.10", "Stages": {"1337": "done"}} diff -Nru ubuntu-report-1.0.11/README.md ubuntu-report-1.1.0/README.md --- ubuntu-report-1.0.11/README.md 2018-04-17 08:20:05.000000000 +0000 +++ ubuntu-report-1.1.0/README.md 2018-05-30 13:19:26.000000000 +0000 @@ -84,6 +84,33 @@ -v, --verbose count[=-1] issue INFO (-v) and DEBUG (-vv) output ``` +### ubuntu-report service + +Try to send periodically previously collected data once network if previous send was unsuccessful + +#### Synopsis + + +Try to send periodically previously collected data once network if previous send was unsuccessful + +``` +ubuntu-report service [flags] +``` + +#### Options + +``` + -h, --help help for service + -u, --url string server url to send report to. Leave empty for default. (default "https://metrics.ubuntu.com") +``` + +#### Options inherited from parent commands + +``` + -f, --force collect and send new report even if already reported + -v, --verbose count[=-1] issue INFO (-v) and DEBUG (-vv) output +``` + ### ubuntu-report show Only collect and display metrics without sending @@ -110,6 +137,14 @@ -v, --verbose count[=-1] issue INFO (-v) and DEBUG (-vv) output ``` +## Service + +In case we can't report (due to limited network or other networking conditions) your report when you act on it, +a little service will kick at login, and try to send the pending report data again. Note that it will exponentially +back off. + +The service won't be active once the pending report is sent. + ## APIS ### Go API @@ -163,6 +198,7 @@ "RAM": 8, "Screens": [ { + "Size": "277mmx156mm", "Resolution": "1366x768", "Frequency": "60.02" }, @@ -178,6 +214,7 @@ "Name": "ubuntu", "Type": "x11" }, + "Language": "fr_FR", "Timezone": "Europe/Paris", "Install": { "Media": "Ubuntu 18.04 LTS \"Bionic Beaver\" - Alpha amd64 (20180305)", diff -Nru ubuntu-report-1.0.11/snap/snapcraft.yaml ubuntu-report-1.1.0/snap/snapcraft.yaml --- ubuntu-report-1.0.11/snap/snapcraft.yaml 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-report-1.1.0/snap/snapcraft.yaml 2018-05-25 08:43:51.000000000 +0000 @@ -0,0 +1,37 @@ +name: ubuntu-report +version: '1.0' +summary: Report hardware and other collected metrics +description: | + Command line tool to report hardware and other collected metrics like + installer or upgrade information. + . + Those information can't be used to identify a single machine and are + presented before being sent to the server. + More details on https://github.com/ubuntu/ubuntu-report +grade: stable +confinement: classic +base: core18 + +apps: + ubuntu-report: + command: bin/ubuntu-report + completer: bash-completion + +parts: + cli: + source: . + plugin: go + go-importpath: github.com/ubuntu/ubuntu-report + override-build: | + snapcraftctl build + GOPATH=`pwd`/../go/ go generate cmd/ubuntu-report/generate_test.go + cp build/bash-completion $SNAPCRAFT_PART_INSTALL/ + stage: + - bin/ubuntu-report + - bash-completion + tests: + plugin: nil + after: [cli] + override-build: | + cd ../../cli/go/src/github.com/ubuntu/ubuntu-report + GOPATH=`pwd`/../../../.. go test ./... diff -Nru ubuntu-report-1.0.11/systemd/ubuntu-report.path ubuntu-report-1.1.0/systemd/ubuntu-report.path --- ubuntu-report-1.0.11/systemd/ubuntu-report.path 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-report-1.1.0/systemd/ubuntu-report.path 2018-05-25 08:43:51.000000000 +0000 @@ -0,0 +1,9 @@ +[Unit] +Description=Pending report trigger for Ubuntu Report +PartOf=default.target + +[Path] +PathExists=%h/.cache/ubuntu-report/pending + +[Install] +WantedBy=default.target diff -Nru ubuntu-report-1.0.11/systemd/ubuntu-report.service ubuntu-report-1.1.0/systemd/ubuntu-report.service --- ubuntu-report-1.0.11/systemd/ubuntu-report.service 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-report-1.1.0/systemd/ubuntu-report.service 2018-05-25 08:43:51.000000000 +0000 @@ -0,0 +1,7 @@ +[Unit] +Description=Ubuntu report sends pending metrics data + +[Service] +Type=simple +ExecStart=/usr/bin/ubuntu-report service +Restart=no diff -Nru ubuntu-report-1.0.11/travis.log ubuntu-report-1.1.0/travis.log --- ubuntu-report-1.0.11/travis.log 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-report-1.1.0/travis.log 2018-05-30 13:40:15.000000000 +0000 @@ -0,0 +1,82 @@ +Command line: +"travis --help" + + + ________ __ + / | / | + ########/ ______ ______ __ __ ##/ _______ + ## | / \ / \ / \ / | / | / | + ## | /###### | ###### | ## \ /##/ ## | /#######/ + ## | ## | ##/ / ## | ## /##/ ## | ## \ + ## | ## | /####### | ## ##/ ## | ###### | + ## | ## | ## ## | ###/ ## | / ##/ + ##/ ##/ #######/ #/ ##/ #######/ + + TRajectory Analyzer and VISualizer - Open-source freeware under GNU GPL v3 + + Copyright (c) Martin Brehm (2009-2017), University of Halle (Saale) + Martin Thomas (2012-2017) + Barbara Kirchner (2009-2017), University of Bonn + + http://www.travis-analyzer.de + + Please cite: M. Brehm, B. Kirchner: J. Chem. Inf. Model. 2011, 51 (8), pp 2007-2023. + + There is absolutely no warranty on any results obtained from TRAVIS. + + # Running on casanier at Wed May 30 15:40:15 2018 (PID 21824). + # Running in /home/didrocks/work/go/src/github.com/ubuntu/ubuntu-report + # Code version: Aug 12 2017, compiled at Jan 14 2018 01:39:14, compiler "7.2.0", GCC 7.2.0 + # Target platform: Linux, compile flags: DEBUG_ARRAYS + # Machine: int=4b, long=8b, addr=8b, 0xA0B0C0D0=D0,C0,B0,A0. + # User home: /home/didrocks, executable: /usr/bin/travis + # Input from terminal, Output to terminal + + >>> Please use a color scheme with dark background or specify "-nocolor"! <<< + + Loading configuration from /home/didrocks/.travis.conf ... + +[Renaming existing File input.txt to #1#input.txt ...OK.] + List of supported command line options: + + -p Loads position data from the specified trajectory file. + The file format may be *.xyz, *.pdb, *.lmp (LAMMPS), HISTORY (DLPOLY), or *.prmtop/*.mdcrd (Amber). + BQB format (*.bqb, *.btr, *.blist) is also supported. + -vel Reads atom velocities from file in addition to main trajectory. + Currently, only .xyz format is supported for velocity data. + -i Reads input from the specified text file. + + -config Load the specified configuration file. + -stream Treats input trajectory as a stream (e.g. named pipe): No fseek, etc. + -showconf Shows a tree structure of the configuration file. + -writeconf Writes the default configuration file, including all defines values. + + -verbose Show detailed information about what's going on. + -nocolor Executes TRAVIS in monochrome mode (suitable for white background). + -dimcolor Uses dim instead of bright colors. + + -credits Display a list of persons who contributed to TRAVIS. + -help, -? Shows this help. + + If only one argument is specified, it is assumed to be the name of a trajectory file. + If argument is specified at all, TRAVIS asks for the trajectory file to open. + + + Note: To show a list of all persons who contributed to TRAVIS, + please add "-credits" to your command line arguments, or set the + variable "SHOWCREDITS" to "TRUE" in your travis.conf file. + + Source code from other projects used in TRAVIS: + - lmfit from Joachim Wuttke + - kiss_fft from Mark Borgerding + - voro++ from Chris Rycroft + + http://www.travis-analyzer.de + + Please cite the following articles: + + * "TRAVIS - A Free Analyzer and Visualizer for Monte Carlo and Molecular Dynamics Trajectories", + M. Brehm, B. Kirchner; J. Chem. Inf. Model. 2011, 51 (8), pp 2007-2023. + +*** The End *** + diff -Nru ubuntu-report-1.0.11/.travis.yml ubuntu-report-1.1.0/.travis.yml --- ubuntu-report-1.0.11/.travis.yml 2018-03-27 08:28:27.000000000 +0000 +++ ubuntu-report-1.1.0/.travis.yml 2018-05-30 15:00:01.000000000 +0000 @@ -20,3 +20,17 @@ after_success: - bash <(curl -s https://codecov.io/bash) + +before_deploy: + - tar cf ubuntu-report-linux-amd64.tar.xz build/ --transform s/build/ubuntu-report-linux-amd64/ +deploy: + provider: releases + file: ubuntu-report-linux-amd64.tar.xz + api_key: + secure: cMSOmykNNeNIGbA9zBHRR7JP4iBuaB/v8EY3fjlNI7IjSQAW/9YsGi3g1syYUH3Hy31VQQh8dICocn2eWq6BG0WkUyyJb3XnB6hvwW+CwKCMWMxHFMjVsePLkLnrFNhazlbgJF1BvA7fDTVWvARwGT9FEIOJGkMKcjUBZOIpdGJNKcERPcV5SiCSQEhmVrxln4sQGFmENsgX2/467NIPy3dZSg/7ZiRKc4xRtiib7OKdGUannc5CnEyCX9pilsMtFwemZYOLQ6Hp0nOnGM2TrQnvTBZAmyFp23YRnMtgvDfLvyLp7zD/UEbD0eOxjZP7s3weyAvRIr1NtQZqwvUfz8+aAU9eLJxJVuXv749kbRt9N/p1NPob9GZuBL0YG1klIP7lmzfAMOyLaqvhgk377RbqDXzwdLsriNsCp4stLjWQCbMO/Pppk1b2GVEjIHe0VP5qXaC5doLA+hZmfrfoJsE5UguD4/u5A2I1cRibemj8joHs0iUleML9yUj/VNZMgAs+skMaWL8JaGBhNn84gkiO+A/zZL9gvpewZiabS9k4heY+mk5XzcxbdDf0VwRVUJSNjV+GbN2/8ORrgAFUPB5NWUn4Pe/Qq+e+5AicFG6xeUBh0PW05tnXYxrQTsXf9NhKJCESTj90FCnDI11SYfwIDufXaT6nGqh51kJx3/8= + skip_cleanup: true + on: + tags: true + repo: ubuntu/ubuntu-report + branch: master + condition: $TRAVIS_GO_VERSION != master Binary files /tmp/tmpiK9cAs/IexQee70pr/ubuntu-report-1.0.11/ubuntu-report-linux-amd64.tar.xz and /tmp/tmpiK9cAs/PLGecVH7uP/ubuntu-report-1.1.0/ubuntu-report-linux-amd64.tar.xz differ diff -Nru ubuntu-report-1.0.11/.vscode/settings.json ubuntu-report-1.1.0/.vscode/settings.json --- ubuntu-report-1.0.11/.vscode/settings.json 1970-01-01 00:00:00.000000000 +0000 +++ ubuntu-report-1.1.0/.vscode/settings.json 2018-05-25 08:53:42.000000000 +0000 @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file