|
7 | 7 | "path" |
8 | 8 | "runtime" |
9 | 9 | "slices" |
| 10 | + "strings" |
10 | 11 | "syscall" |
11 | 12 | "testing" |
12 | 13 | "time" |
@@ -85,6 +86,7 @@ var dapBuildTests = []func(t *testing.T, sb integration.Sandbox){ |
85 | 86 | testDapBuildStepNext, |
86 | 87 | testDapBuildStepOut, |
87 | 88 | testDapBuildVariables, |
| 89 | + testDapBuildDeferredEval, |
88 | 90 | } |
89 | 91 |
|
90 | 92 | func testDapBuild(t *testing.T, sb integration.Sandbox) { |
@@ -857,6 +859,61 @@ func testDapBuildVariables(t *testing.T, sb integration.Sandbox) { |
857 | 859 | } |
858 | 860 | } |
859 | 861 |
|
| 862 | +func testDapBuildDeferredEval(t *testing.T, sb integration.Sandbox) { |
| 863 | + dir := createTestProject(t) |
| 864 | + client, done, err := dapBuildCmd(t, sb) |
| 865 | + require.NoError(t, err) |
| 866 | + |
| 867 | + // Track when we see this message. |
| 868 | + seen := make(chan struct{}, 1) |
| 869 | + client.RegisterEvent("output", func(em dap.EventMessage) { |
| 870 | + e := em.(*dap.OutputEvent) |
| 871 | + if strings.Contains(e.Body.Output, "RUN cp /etc/foo /etc/bar") { |
| 872 | + select { |
| 873 | + case seen <- struct{}{}: |
| 874 | + default: |
| 875 | + } |
| 876 | + } |
| 877 | + }) |
| 878 | + |
| 879 | + interruptCh := pollInterruptEvents(client) |
| 880 | + doLaunch(t, client, commands.LaunchConfig{ |
| 881 | + Dockerfile: path.Join(dir, "Dockerfile"), |
| 882 | + ContextPath: dir, |
| 883 | + }, |
| 884 | + dap.SourceBreakpoint{Line: 7}, |
| 885 | + ) |
| 886 | + |
| 887 | + stopped := waitForInterrupt[*dap.StoppedEvent](t, interruptCh) |
| 888 | + require.NotNil(t, stopped) |
| 889 | + |
| 890 | + // The output event is usually immediate but it can sometimes be delayed due to |
| 891 | + // the multithreading in the printer. Just wait for a little bit. |
| 892 | + select { |
| 893 | + case <-seen: |
| 894 | + // We should not have seen this message since the branch this |
| 895 | + // message comes from should be deferred because we have |
| 896 | + // not passed the breakpoint. |
| 897 | + t.Fatal("step has been invoked before intended") |
| 898 | + case <-time.After(100 * time.Millisecond): |
| 899 | + } |
| 900 | + |
| 901 | + doNext(t, client, stopped.Body.ThreadId) |
| 902 | + |
| 903 | + stopped = waitForInterrupt[*dap.StoppedEvent](t, interruptCh) |
| 904 | + require.NotNil(t, stopped) |
| 905 | + |
| 906 | + select { |
| 907 | + case <-seen: |
| 908 | + // Wait up to a second for the input to be seen. |
| 909 | + case <-time.After(time.Second): |
| 910 | + t.Fatal("step should have been seen") |
| 911 | + } |
| 912 | + |
| 913 | + var exitErr *exec.ExitError |
| 914 | + require.ErrorAs(t, done(true), &exitErr) |
| 915 | +} |
| 916 | + |
860 | 917 | func doLaunch(t *testing.T, client *daptest.Client, config commands.LaunchConfig, bps ...dap.SourceBreakpoint) { |
861 | 918 | t.Helper() |
862 | 919 |
|
|
0 commit comments