示例#1
0
func TestParserRoundTrip(t *testing.T) {
	for _, tc := range mtailPrograms {
		p := newParser(tc.name, strings.NewReader(tc.program), metrics.NewStore())
		r := mtailParse(p)

		if r != 0 || p.root == nil || len(p.errors) > 0 {
			t.Errorf("1st pass parse errors:\n")
			for _, e := range p.errors {
				t.Errorf("\t%s\n", e)
			}
			continue
		}

		u := Unparser{}
		output := u.Unparse(p.root)

		p2 := newParser(tc.name+" 2", strings.NewReader(output), metrics.NewStore())
		r = mtailParse(p2)
		if r != 0 || p2.root == nil || len(p2.errors) > 0 {
			t.Errorf("2nd pass parse errors:\n")
			for _, e := range p2.errors {
				t.Errorf("\t%s\n", e)
			}
			continue
		}

		u = Unparser{}
		output2 := u.Unparse(p2.root)

		diff := pretty.Compare(output2, output)
		if len(diff) > 0 {
			t.Errorf("Round trip failed to generate same output.\n%s", diff)
		}
	}
}
示例#2
0
func TestHandlePrometheus(t *testing.T) {
	for _, tc := range handlePrometheusTests {
		ms := metrics.NewStore()
		for _, metric := range tc.metrics {
			ms.Add(metric)
		}
		o := Options{ms, "gunstar"}
		e, err := New(o)
		if err != nil {
			t.Fatalf("couldn't make exporter: %s", err)
		}
		response := httptest.NewRecorder()
		e.HandlePrometheusMetrics(response, &http.Request{})
		if response.Code != 200 {
			t.Errorf("test case %s: response code not 200: %d", tc.name, response.Code)
		}
		b, err := ioutil.ReadAll(response.Body)
		if err != nil {
			t.Errorf("test case %s: failed to read response: %s", tc.name, err)
		}
		diff := pretty.Compare(string(b), tc.expected)
		if len(diff) > 0 {
			t.Errorf("test case %s: response not expected:\n%s", tc.name, diff)
		}
	}
}
示例#3
0
func TestCompileAndRun(t *testing.T) {
	var testProgram = "/$/ {}\n"
	store := metrics.NewStore()
	lines := make(chan string)
	w := watcher.NewFakeWatcher()
	fs := afero.NewMemMapFs()
	o := LoaderOptions{store, lines, w, fs, false, false, true}
	l, err := NewLoader(o)
	if err != nil {
		t.Fatalf("couldn't create loader: %s", err)
	}
	if err := l.CompileAndRun("Test", strings.NewReader(testProgram)); err != nil {
		t.Errorf("CompileAndRun returned error: %s", err)
	}
	l.handleMu.Lock()
	if len(l.handles) < 1 {
		t.Errorf("no vm handles: %v", l.handles)
	}
	l.handleMu.Unlock()
	l.handleMu.Lock()
	c := l.handles["Test"].done
	if c == nil {
		t.Errorf("No done channel in handles: %v", l.handles)
	}
	l.handleMu.Unlock()
	close(lines)
	<-c
	{
		l.handleMu.Lock()
		defer l.handleMu.Unlock()
		if len(l.handles) != 0 {
			t.Errorf("some vm handles: %v", l.handles)
		}
	}
}
示例#4
0
func TestReadTestData(t *testing.T) {
	f, err := os.Open("reader_test.golden")
	if err != nil {
		t.Fatal(err)
	}
	defer f.Close()
	store := metrics.NewStore()
	ReadTestData(f, "reader_test", store)
	diff := pretty.Compare(expectedMetrics, store.Metrics)
	if len(diff) > 0 {
		t.Errorf("metrics don't match: %s\n", diff)
	}
}
示例#5
0
func TestInvalidPrograms(t *testing.T) {
	for _, tc := range InvalidPrograms {
		p := newParser(tc.name, strings.NewReader(tc.program), metrics.NewStore())
		mtailParse(p)

		diff := pretty.Compare(
			strings.Join(tc.errors, "\n"),             // want
			strings.TrimRight(p.errors.Error(), "\n")) // got
		if len(diff) > 0 {
			t.Errorf("Incorrect error for '%s'\n%s", tc.name, diff)
		}
	}
}
示例#6
0
func TestExamplePrograms(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test in short mode")
	}
	for _, tc := range exampleProgramTests {
		w := watcher.NewFakeWatcher()
		store := metrics.NewStore()
		o := mtail.Options{Progs: tc.programfile, W: w, Store: store}
		mtail, err := mtail.New(o)
		if err != nil {
			t.Fatalf("create mtail failed: %s", err)
		}

		if _, err := mtail.OneShot(tc.logfile, false); err != nil {
			t.Errorf("Oneshot failed for %s: %s", tc.logfile, err)
			continue
		}

		j, err := os.Open(tc.jsonfile)
		if err != nil {
			t.Fatalf("%s: could not open json file: %s", tc.jsonfile, err)
		}
		defer j.Close()

		golden_store := metrics.NewStore()
		testdata.ReadTestData(j, tc.programfile, golden_store)

		mtail.Close()

		diff := pretty.Compare(golden_store, store)

		if len(diff) > 0 {
			t.Errorf("%s: metrics don't match:\n%s", tc.programfile, diff)

			t.Errorf("Store metrics: %#v", store.Metrics)
		}
	}
}
示例#7
0
func TestCompile(t *testing.T) {
	for _, tc := range programs {
		m := metrics.NewStore()
		v, err := Compile(tc.name, strings.NewReader(tc.source), m, false, true)
		if err != nil {
			t.Errorf("Compile errors: %q", err)
			continue
		}
		diff := pretty.Compare(tc.prog, v.prog)
		if len(diff) > 0 {
			t.Errorf("%s: VM prog doesn't match.\n%s", tc.name, diff)
		}
	}
}
示例#8
0
func TestMetricToCollectd(t *testing.T) {
	ts, terr := time.Parse("2006/01/02 15:04:05", "2012/07/24 10:14:00")
	if terr != nil {
		t.Errorf("time parse error: %s", terr)
	}
	ms := metrics.NewStore()

	scalarMetric := metrics.NewMetric("foo", "prog", metrics.Counter)
	d, _ := scalarMetric.GetDatum()
	d.Set(37, ts)
	ms.Add(scalarMetric)

	r := FakeSocketWrite(metricToCollectd, scalarMetric)
	expected := []string{"PUTVAL \"gunstar/mtail-prog/counter-foo\" interval=60 1343124840:37\n"}
	diff := pretty.Compare(r, expected)
	if len(diff) > 0 {
		t.Errorf("String didn't match:\n%s", diff)
	}

	dimensionedMetric := metrics.NewMetric("bar", "prog", metrics.Gauge, "label")
	d, _ = dimensionedMetric.GetDatum("quux")
	d.Set(37, ts)
	d, _ = dimensionedMetric.GetDatum("snuh")
	d.Set(37, ts)
	ms.ClearMetrics()
	ms.Add(dimensionedMetric)

	r = FakeSocketWrite(metricToCollectd, dimensionedMetric)
	expected = []string{
		"PUTVAL \"gunstar/mtail-prog/gauge-bar-label-quux\" interval=60 1343124840:37\n",
		"PUTVAL \"gunstar/mtail-prog/gauge-bar-label-snuh\" interval=60 1343124840:37\n"}
	diff = pretty.Compare(r, expected)
	if len(diff) > 0 {
		t.Errorf("String didn't match:\n%s", diff)
	}

	timingMetric := metrics.NewMetric("foo", "prog", metrics.Timer)
	d, _ = timingMetric.GetDatum()
	d.Set(123, ts)
	ms.Add(timingMetric)

	r = FakeSocketWrite(metricToCollectd, timingMetric)
	expected = []string{"PUTVAL \"gunstar/mtail-prog/gauge-foo\" interval=60 1343124840:123\n"}
	diff = pretty.Compare(r, expected)
	if len(diff) > 0 {
		t.Errorf("String didn't match:\n%s", diff)
	}
}
示例#9
0
// New creates an Mtail from the supplied Options.
func New(o Options) (*Mtail, error) {
	store := o.Store
	if store == nil {
		store = metrics.NewStore()
	}
	m := &Mtail{
		lines:   make(chan string),
		store:   store,
		webquit: make(chan struct{}),
		o:       o}

	err := m.InitLoader()
	if err != nil {
		return nil, err
	}

	m.e, err = exporter.New(exporter.Options{Store: m.store})
	if err != nil {
		return nil, err
	}

	return m, nil
}
示例#10
0
func TestNewLoader(t *testing.T) {
	w := watcher.NewFakeWatcher()
	store := metrics.NewStore()
	inLines := make(chan string)
	fs := afero.NewMemMapFs()
	o := LoaderOptions{store, inLines, w, fs, false, false, true}
	l, err := NewLoader(o)
	if err != nil {
		t.Fatalf("couldn't create loader: %s", err)
	}
	done := make(chan struct{})
	outLines := make(chan string)
	handle := &vmHandle{outLines, done}
	l.handleMu.Lock()
	l.handles["test"] = handle
	l.handleMu.Unlock()
	go func() {
		for _ = range outLines {
		}
		close(done)
	}()
	close(inLines)
	<-outLines
}
示例#11
0
func TestProcessEvents(t *testing.T) {
	for _, tt := range testProcessEvents {
		w := watcher.NewFakeWatcher()
		w.Add(".")
		store := metrics.NewStore()
		lines := make(chan string)
		fs := afero.NewMemMapFs()
		o := LoaderOptions{store, lines, w, fs, false, false, true}
		l, err := NewLoader(o)
		if err != nil {
			t.Fatalf("couldn't create loader: %s", err)
		}
		for i := range tt.events {
			e := tt.events[i]
			switch e := e.(type) {
			case watcher.CreateEvent:
				if e.Pathname != "notexist.mtail" {
					_, err := fs.Create(e.Pathname)
					if err != nil {
						t.Fatalf("Create failed for %s: %s", e.Pathname, err)
					}
				}
				w.InjectCreate(e.Pathname)
			case watcher.DeleteEvent:
				err := fs.Remove(e.Pathname)
				if err != nil {
					t.Fatalf("Remove failed for %s: %s", e.Pathname, err)
				}
				w.InjectDelete(e.Pathname)
			case watcher.UpdateEvent:
				if e.Pathname != "notexist.mtail" {
					f, err := fs.Create(e.Pathname)
					if err != nil {
						t.Fatalf("Couldn't open file %s for test: %s", e.Pathname, err)
					}
					_, err = f.WriteString(testProgram)
					if err != nil {
						t.Fatalf("Couldn't write file contents: %s", err)
					}
					if err = f.Close(); err != nil {
						t.Fatalf("Close failed: %s", err)
					}
				}
				w.InjectUpdate(e.Pathname)
			}
		}
		w.Close()
		<-l.watcherDone
		l.handleMu.RLock()
		var programs []string
		for program := range l.handles {
			programs = append(programs, program)
		}
		l.handleMu.RUnlock()
		l.handleMu.RLock()
		if diff := pretty.Compare(tt.expectedPrograms, programs); len(diff) > 0 {
			t.Errorf("%q: loaded programs don't match.\nl.handles: %+#v\n%s", tt.name, l.handles, diff)
		}
		l.handleMu.RUnlock()
		close(lines)

	}
}