From f9f19f36ed23434cea1d8383b83751a547a77f54 Mon Sep 17 00:00:00 2001 From: Mihail Stoykov Date: Thu, 1 Aug 2019 16:53:14 +0300 Subject: [PATCH] fix: Always initialize filesystems for all schemes always This was always done when running a script, but for archives it was deemed not needed as if it wasn't needed during the making of the archive it shouldn't be needed during it's running. The problem arises when a `require` is in a try block in order (to check if something is support for example). In that case if it isn't loaded (for example a nodejs module will not be loaded but will be resolved to an `https` url) it will not be cached. So if someone tries to run an archive from such a script and there were no https imports k6 will panic at runtime. --- js/module_loading_test.go | 39 +++++++++++++++++++++++++++++++++++++++ lib/archive.go | 3 +++ lib/archive_test.go | 1 + 3 files changed, 43 insertions(+) diff --git a/js/module_loading_test.go b/js/module_loading_test.go index c59426e4ed4..c98f04f988d 100644 --- a/js/module_loading_test.go +++ b/js/module_loading_test.go @@ -21,6 +21,7 @@ package js import ( + "bytes" "context" "os" "testing" @@ -359,3 +360,41 @@ func TestBrowserified(t *testing.T) { }) } } +func TestLoadingUnexistingModuleDoesntPanic(t *testing.T) { + fs := afero.NewMemMapFs() + data := `var b; + try { + b = eval("require('buffer')"); + } catch (err) { + b = "correct"; + } + export default function() { + if (b != "correct") { + throw new Error("wrong b "+ JSON.stringify(b)); + } + }` + require.NoError(t, afero.WriteFile(fs, "/script.js", []byte(data), 0644)) + r1, err := getSimpleRunnerWithFileFs("/script.js", data, fs) + require.NoError(t, err) + + arc := r1.MakeArchive() + var buf = &bytes.Buffer{} + require.NoError(t, arc.Write(buf)) + arc, err = lib.ReadArchive(buf) + require.NoError(t, err) + r2, err := NewFromArchive(arc, lib.RuntimeOptions{}) + require.NoError(t, err) + + runners := map[string]*Runner{"Source": r1, "Archive": r2} + for name, r := range runners { + r := r + t.Run(name, func(t *testing.T) { + ch := newDevNullSampleChannel() + defer close(ch) + vu, err := r.NewVU(ch) + require.NoError(t, err) + err = vu.RunOnce(context.Background()) + require.NoError(t, err) + }) + } +} diff --git a/lib/archive.go b/lib/archive.go index f18db2d2c72..b0d4a32b742 100644 --- a/lib/archive.go +++ b/lib/archive.go @@ -109,6 +109,9 @@ func (arc *Archive) getFs(name string) afero.Fs { func ReadArchive(in io.Reader) (*Archive, error) { r := tar.NewReader(in) arc := &Archive{Filesystems: make(map[string]afero.Fs, 2)} + // initialize both fses + _ = arc.getFs("https") + _ = arc.getFs("file") for { hdr, err := r.Next() if err != nil { diff --git a/lib/archive_test.go b/lib/archive_test.go index bc1ffbb043f..09baae58e8d 100644 --- a/lib/archive_test.go +++ b/lib/archive_test.go @@ -368,6 +368,7 @@ func TestStrangePaths(t *testing.T) { assert.Equal(t, arc1, arc2, pathToChange) + arc1Filesystems["https"] = afero.NewMemMapFs() diffMapFilesystems(t, arc1Filesystems, arc2Filesystems) } }