Repository: go-delve/delve
Pull request #2034 (2020-05-01 16:02:46)

Add some simple examples for the list command
These are just some simple examples of how the list command can be used.  I'm not sure how you'd prefer to document these things, so I figured it would be worth throwing something together to at least start a discussion about what you'd prefer.

I was looking at the documentation struggling to remember how to use the list command and some concrete examples would be useful for me.  I essentially grabbed these from your tests.

derekparker: I think it's a good idea to add some more examples. However this new documentation should be added in `pkg/terminal/command.go` in the description for the `list` command. Documentation will then need to be regenerated via `go run _scripts/gen-cli-docs.go`.
colinnewell: Thanks for the pointer.  I have updated the commit accordingly.

Patch:
diff --git a/Documentation/cli/README.md b/Documentation/cli/README.md
index beedda91..0eac6dd8 100644
--- a/Documentation/cli/README.md
+++ b/Documentation/cli/README.md
@@ -348,6 +348,13 @@ Show source code.
 
 Show source around current point or provided linespec.
 
+For example:
+
+	frame 1 list 69
+	list testvariables.go:10000
+	list main.main:30
+	list 40
+
 Aliases: ls l
 
 ## locals
diff --git a/pkg/dwarf/op/op.go b/pkg/dwarf/op/op.go
index 5edcd828..7410f7c1 100644
--- a/pkg/dwarf/op/op.go
+++ b/pkg/dwarf/op/op.go
@@ -54,7 +54,11 @@ func ExecuteStackProgram(regs DwarfRegisters, instructions []byte, ptrSize int)
 		}
 		opcode := Opcode(opcodeByte)
 		if ctxt.reg && opcode != DW_OP_piece {
-			break
+			// last opcode was DW_OP_regN and next one isn't DW_OP_piece so convert
+			// the register piece into a stack value.
+			ctxt.stack = append(ctxt.stack, int64(regs.Uint64Val(ctxt.pieces[len(ctxt.pieces)-1].RegNum)))
+			ctxt.pieces = ctxt.pieces[:len(ctxt.pieces)-1]
+			ctxt.reg = false
 		}
 		fn, ok := oplut[opcode]
 		if !ok {
@@ -68,6 +72,9 @@ func ExecuteStackProgram(regs DwarfRegisters, instructions []byte, ptrSize int)
 	}
 
 	if ctxt.pieces != nil {
+		if len(ctxt.pieces) == 1 && ctxt.pieces[0].IsRegister {
+			return int64(regs.Uint64Val(ctxt.pieces[0].RegNum)), ctxt.pieces, nil
+		}
 		return 0, ctxt.pieces, nil
 	}
 
diff --git a/pkg/proc/bininfo.go b/pkg/proc/bininfo.go
index d4b8d3ab..42d94bfc 100644
--- a/pkg/proc/bininfo.go
+++ b/pkg/proc/bininfo.go
@@ -84,8 +84,6 @@ type BinaryInfo struct {
 
 	frameEntries frame.FrameDescriptionEntries
 
-	compileUnits []*compileUnit // compileUnits is sorted by increasing DWARF offset
-
 	types       map[string]dwarfRef
 	packageVars []packageVar // packageVars is a list of all global/package variables in debug_info, sorted by address
 
@@ -520,14 +518,17 @@ func (err *ErrCouldNotFindLine) Error() string {
 func (bi *BinaryInfo) LineToPC(filename string, lineno int) (pcs []uint64, err error) {
 	fileFound := false
 	var pc uint64
-	for _, cu := range bi.compileUnits {
-		if cu.lineInfo == nil || cu.lineInfo.Lookup[filename] == nil {
-			continue
-		}
-		fileFound = true
-		pc = cu.lineInfo.LineToPC(filename, lineno)
-		if pc != 0 {
-			break
+pcsearch:
+	for _, image := range bi.Images {
+		for _, cu := range image.compileUnits {
+			if cu.lineInfo == nil || cu.lineInfo.Lookup[filename] == nil {
+				continue
+			}
+			fileFound = true
+			pc = cu.lineInfo.LineToPC(filename, lineno)
+			if pc != 0 {
+				break pcsearch
+			}
 		}
 	}
 
@@ -580,9 +581,11 @@ func (bi *BinaryInfo) AllPCsForFileLines(filename string, linenos []int) map[int
 	for _, line := range linenos {
 		r[line] = make([]uint64, 0, 1)
 	}
-	for _, cu := range bi.compileUnits {
-		if cu.lineInfo != nil && cu.lineInfo.Lookup[filename] != nil {
-			cu.lineInfo.AllPCsForFileLines(filename, r)
+	for _, image := range bi.Images {
+		for _, cu := range image.compileUnits {
+			if cu.lineInfo != nil && cu.lineInfo.Lookup[filename] != nil {
+				cu.lineInfo.AllPCsForFileLines(filename, r)
+			}
 		}
 	}
 	return r
@@ -648,6 +651,8 @@ type Image struct {
 
 	typeCache map[dwarf.Offset]godwarf.Type
 
+	compileUnits []*compileUnit // compileUnits is sorted by increasing DWARF offset
+
 	dwarfTreeCache *simplelru.LRU
 
 	// runtimeTypeToDIE maps between the offset of a runtime._type in
@@ -871,7 +876,7 @@ func (bi *BinaryInfo) LocationCovers(entry *dwarf.Entry, attr dwarf.Attr) ([][2]
 	if !ok {
 		return nil, fmt.Errorf("attribute %s of unsupported type %T", attr, a)
 	}
-	cu := bi.findCompileUnitForOffset(entry.Offset)
+	cu := bi.Images[0].findCompileUnitForOffset(entry.Offset)
 	if cu == nil {
 		return nil, errors.New("could not find compile unit")
 	}
@@ -938,17 +943,19 @@ func (bi *BinaryInfo) loclistEntry(off int64, pc uint64) []byte {
 
 // findCompileUnit returns the compile unit containing address pc.
 func (bi *BinaryInfo) findCompileUnit(pc uint64) *compileUnit {
-	for _, cu := range bi.compileUnits {
-		for _, rng := range cu.ranges {
-			if pc >= rng[0] && pc < rng[1] {
-				return cu
+	for _, image := range bi.Images {
+		for _, cu := range image.compileUnits {
+			for _, rng := range cu.ranges {
+				if pc >= rng[0] && pc < rng[1] {
+					return cu
+				}
 			}
 		}
 	}
 	return nil
 }
 
-func (bi *BinaryInfo) findCompileUnitForOffset(off dwarf.Offset) *compileUnit {
+func (bi *Image) findCompileUnitForOffset(off dwarf.Offset) *compileUnit {
 	i := sort.Search(len(bi.compileUnits), func(i int) bool {
 		return bi.compileUnits[i].offset >= off
 	})
@@ -960,7 +967,7 @@ func (bi *BinaryInfo) findCompileUnitForOffset(off dwarf.Offset) *compileUnit {
 
 // Producer returns the value of DW_AT_producer.
 func (bi *BinaryInfo) Producer() string {
-	for _, cu := range bi.compileUnits {
+	for _, cu := range bi.Images[0].compileUnits {
 		if cu.isgo && cu.producer != "" {
 			return cu.producer
 		}
@@ -1569,7 +1576,7 @@ func (bi *BinaryInfo) loadDebugInfoMaps(image *Image, debugLineBytes []byte, wg
 			if cu.isgo && gopkg != "" {
 				bi.PackageMap[gopkg] = append(bi.PackageMap[gopkg], escapePackagePath(strings.Replace(cu.name, "\\", "/", -1)))
 			}
-			bi.compileUnits = append(bi.compileUnits, cu)
+			image.compileUnits = append(image.compileUnits, cu)
 			if entry.Children {
 				bi.loadDebugInfoMapsCompileUnit(ctxt, image, reader, cu)
 			}
@@ -1583,7 +1590,7 @@ func (bi *BinaryInfo) loadDebugInfoMaps(image *Image, debugLineBytes []byte, wg
 		}
 	}
 
-	sort.Sort(compileUnitsByOffset(bi.compileUnits))
+	sort.Sort(compileUnitsByOffset(image.compileUnits))
 	sort.Sort(functionsDebugInfoByEntry(bi.Functions))
 	sort.Sort(packageVarsByAddr(bi.packageVars))
 
@@ -1593,7 +1600,7 @@ func (bi *BinaryInfo) loadDebugInfoMaps(image *Image, debugLineBytes []byte, wg
 	}
 
 	bi.Sources = []string{}
-	for _, cu := range bi.compileUnits {
+	for _, cu := range image.compileUnits {
 		if cu.lineInfo != nil {
 			for _, fileEntry := range cu.lineInfo.FileNames {
 				bi.Sources = append(bi.Sources, fileEntry.Path)
@@ -1997,7 +2004,7 @@ type PackageBuildInfo struct {
 // files constituting the package.
 func (bi *BinaryInfo) ListPackagesBuildInfo(includeFiles bool) []*PackageBuildInfo {
 	m := make(map[string]*PackageBuildInfo)
-	for _, cu := range bi.compileUnits {
+	for _, cu := range bi.Images[0].compileUnits {
 		if cu.image != bi.Images[0] || !cu.isgo || cu.lineInfo == nil {
 			//TODO(aarzilli): what's the correct thing to do for plugins?
 			continue
diff --git a/pkg/proc/eval.go b/pkg/proc/eval.go
index ce85f597..d541bb87 100644
--- a/pkg/proc/eval.go
+++ b/pkg/proc/eval.go
@@ -451,36 +451,33 @@ func regsReplaceStaticBase(regs op.DwarfRegisters, image *Image) op.DwarfRegiste
 
 // PackageVariables returns the name, value, and type of all package variables in the application.
 func (scope *EvalScope) PackageVariables(cfg LoadConfig) ([]*Variable, error) {
-	var vars []*Variable
-	for _, image := range scope.BinInfo.Images {
-		if image.loadErr != nil {
-			continue
+	pkgvars := make([]packageVar, len(scope.BinInfo.packageVars))
+	copy(pkgvars, scope.BinInfo.packageVars)
+	sort.Slice(pkgvars, func(i, j int) bool {
+		if pkgvars[i].cu.image.addr == pkgvars[j].cu.image.addr {
+			return pkgvars[i].offset < pkgvars[j].offset
 		}
-		reader := reader.New(image.dwarf)
-
-		var utypoff dwarf.Offset
-		utypentry, err := reader.SeekToTypeNamed("<unspecified>")
-		if err == nil {
-			utypoff = utypentry.Offset
+		return pkgvars[i].cu.image.addr < pkgvars[j].cu.image.addr
+	})
+	vars := make([]*Variable, 0, len(scope.BinInfo.packageVars))
+	for _, pkgvar := range pkgvars {
+		reader := pkgvar.cu.image.dwarfReader
+		reader.Seek(pkgvar.offset)
+		entry, err := reader.Next()
+		if err != nil {
+			return nil, err
 		}
 
-		for entry, err := reader.NextPackageVariable(); entry != nil; entry, err = reader.NextPackageVariable() {
-			if err != nil {
-				return nil, err
-			}
-
-			if typoff, ok := entry.Val(dwarf.AttrType).(dwarf.Offset); !ok || typoff == utypoff {
-				continue
-			}
-
-			// Ignore errors trying to extract values
-			val, err := extractVarInfoFromEntry(scope.BinInfo, image, regsReplaceStaticBase(scope.Regs, image), scope.Mem, godwarf.EntryToTree(entry))
-			if err != nil {
-				continue
-			}
-			val.loadValue(cfg)
-			vars = append(vars, val)
+		// Ignore errors trying to extract values
+		val, err := extractVarInfoFromEntry(scope.BinInfo, pkgvar.cu.image, regsReplaceStaticBase(scope.Regs, pkgvar.cu.image), scope.Mem, godwarf.EntryToTree(entry))
+		if val.Kind == reflect.Invalid {
+			continue
 		}
+		if err != nil {
+			continue
+		}
+		val.loadValue(cfg)
+		vars = append(vars, val)
 	}
 
 	return vars, nil
diff --git a/pkg/proc/variables.go b/pkg/proc/variables.go
index 7453ba26..b8ad1af5 100644
--- a/pkg/proc/variables.go
+++ b/pkg/proc/variables.go
@@ -588,7 +588,7 @@ func newVariable(name string, addr uintptr, dwarfType godwarf.Type, bi *BinaryIn
 		// b. anonymous struct types (they contain the '{' character)
 		// c. Go internal struct types used to describe maps (they contain the '<'
 		// character).
-		cu := bi.findCompileUnitForOffset(dwarfType.Common().Offset)
+		cu := bi.Images[dwarfType.Common().Index].findCompileUnitForOffset(dwarfType.Common().Offset)
 		if cu != nil && cu.isgo {
 			dwarfType = &godwarf.TypedefType{
 				CommonType: *(dwarfType.Common()),
diff --git a/pkg/terminal/command.go b/pkg/terminal/command.go
index edbf8fb6..5e9c2e7f 100644
--- a/pkg/terminal/command.go
+++ b/pkg/terminal/command.go
@@ -263,7 +263,14 @@ When connected to a headless instance started with the --accept-multiclient, pas
 
 	[goroutine <n>] [frame <m>] list [<linespec>]
 
-Show source around current point or provided linespec.`},
+Show source around current point or provided linespec.
+
+For example:
+
+	frame 1 list 69
+	list testvariables.go:10000
+	list main.main:30
+	list 40`},
 		{aliases: []string{"stack", "bt"}, allowedPrefixes: onPrefix, group: stackCmds, cmdFn: stackCommand, helpMsg: `Print stack trace.
 
 	[goroutine <n>] [frame <m>] stack [<depth>] [-full] [-offsets] [-defer] [-a <n>] [-adepth <depth>] [-mode <mode>]
diff --git a/service/dap/error_ids.go b/service/dap/error_ids.go
index 9f1b9f05..6fbd0b6c 100644
--- a/service/dap/error_ids.go
+++ b/service/dap/error_ids.go
@@ -4,6 +4,7 @@ package dap
 const (
 	UnsupportedCommand int = 9999
 	InternalError      int = 8888
+	NotYetImplemented  int = 7777
 
 	// The values below come from the vscode-go debug adaptor.
 	// Although the spec says they should be unique, the adaptor
diff --git a/service/dap/server.go b/service/dap/server.go
index 3ce27b6c..847de76f 100644
--- a/service/dap/server.go
+++ b/service/dap/server.go
@@ -194,82 +194,150 @@ func (s *Server) handleRequest(request dap.Message) {
 
 	switch request := request.(type) {
 	case *dap.InitializeRequest:
+		// Required
 		s.onInitializeRequest(request)
 	case *dap.LaunchRequest:
+		// Required
 		s.onLaunchRequest(request)
 	case *dap.AttachRequest:
-		s.sendUnsupportedErrorResponse(request.Request)
+		// Required
+		// TODO: implement this request in V0
+		s.onAttachRequest(request)
 	case *dap.DisconnectRequest:
+		// Required
 		s.onDisconnectRequest(request)
 	case *dap.TerminateRequest:
-		s.sendUnsupportedErrorResponse(request.Request)
+		// Optional (capability ‘supportsTerminateRequest‘)
+		// TODO: implement this request in V1
+		s.onTerminateRequest(request)
 	case *dap.RestartRequest:
-		s.sendUnsupportedErrorResponse(request.Request)
+		// Optional (capability ‘supportsRestartRequest’)
+		// TODO: implement this request in V1
+		s.onRestartRequest(request)
 	case *dap.SetBreakpointsRequest:
+		// Required
 		s.onSetBreakpointsRequest(request)
 	case *dap.SetFunctionBreakpointsRequest:
-		s.sendUnsupportedErrorResponse(request.Request)
+		// Optional (capability ‘supportsFunctionBreakpoints’)
+		// TODO: implement this request in V1
+		s.onSetFunctionBreakpointsRequest(request)
 	case *dap.SetExceptionBreakpointsRequest:
+		// Optional (capability ‘exceptionBreakpointFilters’)
 		s.onSetExceptionBreakpointsRequest(request)
 	case *dap.ConfigurationDoneRequest:
+		// Optional (capability ‘supportsConfigurationDoneRequest’)
+		// Supported by vscode-go
 		s.onConfigurationDoneRequest(request)
 	case *dap.ContinueRequest:
+		// Required
 		s.onContinueRequest(request)
 	case *dap.NextRequest:
-		s.sendUnsupportedErrorResponse(request.Request)
+		// Required
+		// TODO: implement this request in V0
+		s.onNextRequest(request)
 	case *dap.StepInRequest:
-		s.sendUnsupportedErrorResponse(request.Request)
+		// Required
+		// TODO: implement this request in V0
+		s.onStepInRequest(request)
 	case *dap.StepOutRequest:
-		s.sendUnsupportedErrorResponse(request.Request)
+		// Required
+		// TODO: implement this request in V0
+		s.onStepOutRequest(request)
 	case *dap.StepBackRequest:
-		s.sendUnsupportedErrorResponse(request.Request)
+		// Optional (capability ‘supportsStepBack’)
+		// TODO: implement this request in V1
+		s.onStepBackRequest(request)
 	case *dap.ReverseContinueRequest:
-		s.sendUnsupportedErrorResponse(request.Request)
+		// Optional (capability ‘supportsStepBack’)
+		// TODO: implement this request in V1
+		s.onReverseContinueRequest(request)
 	case *dap.RestartFrameRequest:
+		// Optional (capability ’supportsRestartFrame’)
 		s.sendUnsupportedErrorResponse(request.Request)
 	case *dap.GotoRequest:
+		// Optional (capability ‘supportsGotoTargetsRequest’)
 		s.sendUnsupportedErrorResponse(request.Request)
 	case *dap.PauseRequest:
-		s.sendUnsupportedErrorResponse(request.Request)
+		// Required
+		// TODO: implement this request in V0
+		s.onPauseRequest(request)
 	case *dap.StackTraceRequest:
-		s.sendUnsupportedErrorResponse(request.Request)
+		// Required
+		// TODO: implement this request in V0
+		s.onStackTraceRequest(request)
 	case *dap.ScopesRequest:
-		s.sendUnsupportedErrorResponse(request.Request)
+		// Required
+		// TODO: implement this request in V0
+		s.onScopesRequest(request)
 	case *dap.VariablesRequest:
-		s.sendUnsupportedErrorResponse(request.Request)
+		// Required
+		// TODO: implement this request in V0
+		s.onVariablesRequest(request)
 	case *dap.SetVariableRequest:
-		s.sendUnsupportedErrorResponse(request.Request)
+		// Optional (capability ‘supportsSetVariable’)
+		// Supported by vscode-go
+		// TODO: implement this request in V0
+		s.onSetVariableRequest(request)
 	case *dap.SetExpressionRequest:
-		s.sendUnsupportedErrorResponse(request.Request)
+		// Optional (capability ‘supportsSetExpression’)
+		// TODO: implement this request in V1
+		s.onSetExpressionRequest(request)
 	case *dap.SourceRequest:
+		// Required
+		// This does not make sense in the context of Go as
+		// the source cannot be a string eval'ed at runtime.
 		s.sendUnsupportedErrorResponse(request.Request)
 	case *dap.ThreadsRequest:
+		// Required
 		s.onThreadsRequest(request)
 	case *dap.TerminateThreadsRequest:
+		// Optional (capability ‘supportsTerminateThreadsRequest’)
 		s.sendUnsupportedErrorResponse(request.Request)
 	case *dap.EvaluateRequest:
-		s.sendUnsupportedErrorResponse(request.Request)
+		// Required - TODO
+		// TODO: implement this request in V0
+		s.onEvaluateRequest(request)
 	case *dap.StepInTargetsRequest:
+		// Optional (capability ‘supportsStepInTargetsRequest’)
 		s.sendUnsupportedErrorResponse(request.Request)
 	case *dap.GotoTargetsRequest:
+		// Optional (capability ‘supportsGotoTargetsRequest’)
 		s.sendUnsupportedErrorResponse(request.Request)
 	case *dap.CompletionsRequest:
+		// Optional (capability ‘supportsCompletionsRequest’)
 		s.sendUnsupportedErrorResponse(request.Request)
 	case *dap.ExceptionInfoRequest:
+		// Optional (capability ‘supportsExceptionInfoRequest’)
+		// TODO: does this request make sense for delve?
 		s.sendUnsupportedErrorResponse(request.Request)
 	case *dap.LoadedSourcesRequest:
-		s.sendUnsupportedErrorResponse(request.Request)
+		// Optional (capability ‘supportsLoadedSourcesRequest’)
+		// TODO: implement this request in V1
+		s.onLoadedSourcesRequest(request)
 	case *dap.DataBreakpointInfoRequest:
+		// Optional (capability ‘supportsDataBreakpoints’)
 		s.sendUnsupportedErrorResponse(request.Request)
 	case *dap.SetDataBreakpointsRequest:
+		// Optional (capability ‘supportsDataBreakpoints’)
 		s.sendUnsupportedErrorResponse(request.Request)
 	case *dap.ReadMemoryRequest:
-		s.sendUnsupportedErrorResponse(request.Request)
+		// Optional (capability ‘supportsReadMemoryRequest‘)
+		// TODO: implement this request in V1
+		s.onReadMemoryRequest(request)
 	case *dap.DisassembleRequest:
-		s.sendUnsupportedErrorResponse(request.Request)
+		// Optional (capability ‘supportsDisassembleRequest’)
+		// TODO: implement this request in V1
+		s.onDisassembleRequest(request)
 	case *dap.CancelRequest:
-		s.sendUnsupportedErrorResponse(request.Request)
+		// Optional (capability ‘supportsCancelRequest’)
+		// TODO: does this request make sense for delve?
+		s.onCancelRequest(request)
 	case *dap.BreakpointLocationsRequest:
+		// Optional (capability ‘supportsBreakpointLocationsRequest’)
+		s.sendUnsupportedErrorResponse(request.Request)
+	case *dap.ModulesRequest:
+		// Optional (capability ‘supportsModulesRequest’)
+		// TODO: does this request make sense for delve?
 		s.sendUnsupportedErrorResponse(request.Request)
 	default:
 		// This is a DAP message that go-dap has a struct for, so
@@ -291,6 +359,16 @@ func (s *Server) onInitializeRequest(request *dap.InitializeRequest) {
 	response.Body.SupportsConfigurationDoneRequest = true
 	// TODO(polina): support this to match vscode-go functionality
 	response.Body.SupportsSetVariable = false
+	// TODO(polina): support these requests in addition to vscode-go feature parity
+	response.Body.SupportsTerminateRequest = false
+	response.Body.SupportsRestartRequest = false
+	response.Body.SupportsFunctionBreakpoints = false
+	response.Body.SupportsStepBack = false
+	response.Body.SupportsSetExpression = false
+	response.Body.SupportsLoadedSourcesRequest = false
+	response.Body.SupportsReadMemoryRequest = false
+	response.Body.SupportsDisassembleRequest = false
+	response.Body.SupportsCancelRequest = false
 	s.send(response)
 }
 
@@ -422,7 +500,7 @@ func (s *Server) onSetBreakpointsRequest(request *dap.SetBreakpointsRequest) {
 
 func (s *Server) onSetExceptionBreakpointsRequest(request *dap.SetExceptionBreakpointsRequest) {
 	// Unlike what DAP documentation claims, this request is always sent
-	// even though we specified no filters at initializatin. Handle as no-op.
+	// even though we specified no filters at initialization. Handle as no-op.
 	s.send(&dap.SetExceptionBreakpointsResponse{Response: *newResponse(request.Request)})
 }
 
@@ -488,6 +566,126 @@ func (s *Server) onThreadsRequest(request *dap.ThreadsRequest) {
 	s.send(response)
 }
 
+// onAttachRequest sends a not-yet-implemented error response.
+// This is a mandatory request to support.
+func (s *Server) onAttachRequest(request *dap.AttachRequest) { // TODO V0
+	s.sendNotYetImplementedErrorResponse(request.Request)
+}
+
+// onNextRequest sends a not-yet-implemented error response.
+// This is a mandatory request to support.
+func (s *Server) onNextRequest(request *dap.NextRequest) { // TODO V0
+	s.sendNotYetImplementedErrorResponse(request.Request)
+}
+
+// onStepInRequest sends a not-yet-implemented error response.
+// This is a mandatory request to support.
+func (s *Server) onStepInRequest(request *dap.StepInRequest) { // TODO V0
+	s.sendNotYetImplementedErrorResponse(request.Request)
+}
+
+// onStepOutRequest sends a not-yet-implemented error response.
+// This is a mandatory request to support.
+func (s *Server) onStepOutRequest(request *dap.StepOutRequest) { // TODO V0
+	s.sendNotYetImplementedErrorResponse(request.Request)
+}
+
+// onPauseRequest sends a not-yet-implemented error response.
+// This is a mandatory request to support.
+func (s *Server) onPauseRequest(request *dap.PauseRequest) { // TODO V0
+	s.sendNotYetImplementedErrorResponse(request.Request)
+}
+
+// onStackTraceRequest sends a not-yet-implemented error response.
+// This is a mandatory request to support.
+func (s *Server) onStackTraceRequest(request *dap.StackTraceRequest) { // TODO V0
+	s.sendNotYetImplementedErrorResponse(request.Request)
+}
+
+// onScopesRequest sends a not-yet-implemented error response.
+// This is a mandatory request to support.
+func (s *Server) onScopesRequest(request *dap.ScopesRequest) { // TODO V0
+	s.sendNotYetImplementedErrorResponse(request.Request)
+}
+
+// onVariablesRequest sends a not-yet-implemented error response.
+// This is a mandatory request to support.
+func (s *Server) onVariablesRequest(request *dap.VariablesRequest) { // TODO V0
+	s.sendNotYetImplementedErrorResponse(request.Request)
+}
+
+// onEvaluateRequest sends a not-yet-implemented error response.
+// This is a mandatory request to support.
+func (s *Server) onEvaluateRequest(request *dap.EvaluateRequest) { // TODO V0
+	s.sendNotYetImplementedErrorResponse(request.Request)
+}
+
+// onTerminateRequest sends a not-yet-implemented error response.
+// Capability 'supportsTerminateRequest' is not set in 'initialize' response.
+func (s *Server) onTerminateRequest(request *dap.TerminateRequest) {
+	s.sendNotYetImplementedErrorResponse(request.Request)
+}
+
+// onRestartRequest sends a not-yet-implemented error response
+// Capability 'supportsRestartRequest' is not set in 'initialize' response.
+func (s *Server) onRestartRequest(request *dap.RestartRequest) {
+	s.sendNotYetImplementedErrorResponse(request.Request)
+}
+
+// onSetFunctionBreakpointsRequest sends a not-yet-implemented error response.
+// Capability 'supportsFunctionBreakpoints' is not set 'initialize' response.
+func (s *Server) onSetFunctionBreakpointsRequest(request *dap.SetFunctionBreakpointsRequest) {
+	s.sendNotYetImplementedErrorResponse(request.Request)
+}
+
+// onStepBackRequest sends a not-yet-implemented error response.
+// Capability 'supportsStepBack' is not set 'initialize' response.
+func (s *Server) onStepBackRequest(request *dap.StepBackRequest) {
+	s.sendNotYetImplementedErrorResponse(request.Request)
+}
+
+// onReverseContinueRequest sends a not-yet-implemented error response.
+// Capability 'supportsStepBack' is not set 'initialize' response.
+func (s *Server) onReverseContinueRequest(request *dap.ReverseContinueRequest) {
+	s.sendNotYetImplementedErrorResponse(request.Request)
+}
+
+// onSetVariableRequest sends a not-yet-implemented error response.
+// Capability 'supportsSetVariable' is not set 'initialize' response.
+func (s *Server) onSetVariableRequest(request *dap.SetVariableRequest) { // TODO V0
+	s.sendNotYetImplementedErrorResponse(request.Request)
+}
+
+// onSetExpression sends a not-yet-implemented error response.
+// Capability 'supportsSetExpression' is not set 'initialize' response.
+func (s *Server) onSetExpressionRequest(request *dap.SetExpressionRequest) {
+	s.sendNotYetImplementedErrorResponse(request.Request)
+}
+
+// onLoadedSourcesRequest sends a not-yet-implemented error response.
+// Capability 'supportsLoadedSourcesRequest' is not set 'initialize' response.
+func (s *Server) onLoadedSourcesRequest(request *dap.LoadedSourcesRequest) {
+	s.sendNotYetImplementedErrorResponse(request.Request)
+}
+
+// onReadMemoryRequest sends a not-yet-implemented error response.
+// Capability 'supportsReadMemoryRequest' is not set 'initialize' response.
+func (s *Server) onReadMemoryRequest(request *dap.ReadMemoryRequest) {
+	s.sendNotYetImplementedErrorResponse(request.Request)
+}
+
+// onDisassembleRequest sends a not-yet-implemented error response.
+// Capability 'supportsDisassembleRequest' is not set 'initialize' response.
+func (s *Server) onDisassembleRequest(request *dap.DisassembleRequest) {
+	s.sendNotYetImplementedErrorResponse(request.Request)
+}
+
+// onCancelRequest sends a not-yet-implemented error response.
+// Capability 'supportsCancelRequest' is not set 'initialize' response.
+func (s *Server) onCancelRequest(request *dap.CancelRequest) {
+	s.sendNotYetImplementedErrorResponse(request.Request)
+}
+
 func (s *Server) sendErrorResponse(request dap.Request, id int, summary string, details string) {
 	er := &dap.ErrorResponse{}
 	er.Type = "response"
@@ -521,6 +719,11 @@ func (s *Server) sendUnsupportedErrorResponse(request dap.Request) {
 		fmt.Sprintf("cannot process '%s' request", request.Command))
 }
 
+func (s *Server) sendNotYetImplementedErrorResponse(request dap.Request) {
+	s.sendErrorResponse(request, NotYetImplemented, "Not yet implemented",
+		fmt.Sprintf("cannot process '%s' request", request.Command))
+}
+
 func newResponse(request dap.Request) *dap.Response {
 	return &dap.Response{
 		ProtocolMessage: dap.ProtocolMessage{


Test patch:
diff --git a/pkg/proc/proc_test.go b/pkg/proc/proc_test.go
index ce29f5a7..d0b7ad44 100644
--- a/pkg/proc/proc_test.go
+++ b/pkg/proc/proc_test.go
@@ -1827,6 +1827,14 @@ func TestIssue414(t *testing.T) {
 }
 
 func TestPackageVariables(t *testing.T) {
+	var skippedVariable = map[string]bool{
+		"runtime.uint16Eface": true,
+		"runtime.uint32Eface": true,
+		"runtime.uint64Eface": true,
+		"runtime.stringEface": true,
+		"runtime.sliceEface":  true,
+	}
+
 	protest.AllowRecording(t)
 	withTestProcess("testvariables", t, func(p *proc.Target, fixture protest.Fixture) {
 		err := p.Continue()
@@ -1837,6 +1845,9 @@ func TestPackageVariables(t *testing.T) {
 		assertNoError(err, t, "PackageVariables()")
 		failed := false
 		for _, v := range vars {
+			if skippedVariable[v.Name] {
+				continue
+			}
 			if v.Unreadable != nil && v.Unreadable.Error() != "no location attribute Location" {
 				failed = true
 				t.Logf("Unreadable variable %s: %v", v.Name, v.Unreadable)
diff --git a/service/dap/daptest/client.go b/service/dap/daptest/client.go
index 1a97e428..67a70966 100644
--- a/service/dap/daptest/client.go
+++ b/service/dap/daptest/client.go
@@ -59,14 +59,33 @@ func (c *Client) expectReadProtocolMessage(t *testing.T) dap.Message {
 	return m
 }
 
-func (c *Client) ExpectDisconnectResponse(t *testing.T) *dap.DisconnectResponse {
+func (c *Client) ExpectErrorResponse(t *testing.T) *dap.ErrorResponse {
 	t.Helper()
-	return c.expectReadProtocolMessage(t).(*dap.DisconnectResponse)
+	return c.expectReadProtocolMessage(t).(*dap.ErrorResponse)
 }
 
-func (c *Client) ExpectErrorResponse(t *testing.T) *dap.ErrorResponse {
+func (c *Client) expectErrorResponse(t *testing.T, id int, message string) *dap.ErrorResponse {
 	t.Helper()
-	return c.expectReadProtocolMessage(t).(*dap.ErrorResponse)
+	er := c.expectReadProtocolMessage(t).(*dap.ErrorResponse)
+	if er.Body.Error.Id != id || er.Message != message {
+		t.Errorf("\ngot %#v\nwant Id=%d Message=%q", er, id, message)
+	}
+	return er
+}
+
+func (c *Client) ExpectNotYetImplementedErrorResponse(t *testing.T) *dap.ErrorResponse {
+	t.Helper()
+	return c.expectErrorResponse(t, 7777, "Not yet implemented")
+}
+
+func (c *Client) ExpectUnsupportedCommandErrorResponse(t *testing.T) *dap.ErrorResponse {
+	t.Helper()
+	return c.expectErrorResponse(t, 9999, "Unsupported command")
+}
+
+func (c *Client) ExpectDisconnectResponse(t *testing.T) *dap.DisconnectResponse {
+	t.Helper()
+	return c.expectReadProtocolMessage(t).(*dap.DisconnectResponse)
 }
 
 func (c *Client) ExpectContinueResponse(t *testing.T) *dap.ContinueResponse {
@@ -128,6 +147,106 @@ func (c *Client) ExpectStackTraceResponse(t *testing.T) *dap.StackTraceResponse
 	return c.expectReadProtocolMessage(t).(*dap.StackTraceResponse)
 }
 
+func (c *Client) ExpectTerminateResponse(t *testing.T) *dap.TerminateResponse {
+	t.Helper()
+	return c.expectReadProtocolMessage(t).(*dap.TerminateResponse)
+}
+
+func (c *Client) ExpectRestartResponse(t *testing.T) *dap.RestartResponse {
+	t.Helper()
+	return c.expectReadProtocolMessage(t).(*dap.RestartResponse)
+}
+
+func (c *Client) ExpectSetFunctionBreakpointsResponse(t *testing.T) *dap.SetFunctionBreakpointsResponse {
+	t.Helper()
+	return c.expectReadProtocolMessage(t).(*dap.SetFunctionBreakpointsResponse)
+}
+
+func (c *Client) ExpectStepBackResponse(t *testing.T) *dap.StepBackResponse {
+	t.Helper()
+	return c.expectReadProtocolMessage(t).(*dap.StepBackResponse)
+}
+
+func (c *Client) ExpectReverseContinueResponse(t *testing.T) *dap.ReverseContinueResponse {
+	t.Helper()
+	return c.expectReadProtocolMessage(t).(*dap.ReverseContinueResponse)
+}
+
+func (c *Client) ExpectRestartFrameResponse(t *testing.T) *dap.RestartFrameResponse {
+	t.Helper()
+	return c.expectReadProtocolMessage(t).(*dap.RestartFrameResponse)
+}
+
+func (c *Client) ExpectSetExpressionResponse(t *testing.T) *dap.SetExpressionResponse {
+	t.Helper()
+	return c.expectReadProtocolMessage(t).(*dap.SetExpressionResponse)
+}
+
+func (c *Client) ExpectTerminateThreadsResponse(t *testing.T) *dap.TerminateThreadsResponse {
+	t.Helper()
+	return c.expectReadProtocolMessage(t).(*dap.TerminateThreadsResponse)
+}
+
+func (c *Client) ExpectStepInTargetsResponse(t *testing.T) *dap.StepInTargetsResponse {
+	t.Helper()
+	return c.expectReadProtocolMessage(t).(*dap.StepInTargetsResponse)
+}
+
+func (c *Client) ExpectGotoTargetsResponse(t *testing.T) *dap.GotoTargetsResponse {
+	t.Helper()
+	return c.expectReadProtocolMessage(t).(*dap.GotoTargetsResponse)
+}
+
+func (c *Client) ExpectCompletionsResponse(t *testing.T) *dap.CompletionsResponse {
+	t.Helper()
+	return c.expectReadProtocolMessage(t).(*dap.CompletionsResponse)
+}
+
+func (c *Client) ExpectExceptionInfoResponse(t *testing.T) *dap.ExceptionInfoResponse {
+	t.Helper()
+	return c.expectReadProtocolMessage(t).(*dap.ExceptionInfoResponse)
+}
+
+func (c *Client) ExpectLoadedSourcesResponse(t *testing.T) *dap.LoadedSourcesResponse {
+	t.Helper()
+	return c.expectReadProtocolMessage(t).(*dap.LoadedSourcesResponse)
+}
+
+func (c *Client) ExpectDataBreakpointInfoResponse(t *testing.T) *dap.DataBreakpointInfoResponse {
+	t.Helper()
+	return c.expectReadProtocolMessage(t).(*dap.DataBreakpointInfoResponse)
+}
+
+func (c *Client) ExpectSetDataBreakpointsResponse(t *testing.T) *dap.SetDataBreakpointsResponse {
+	t.Helper()
+	return c.expectReadProtocolMessage(t).(*dap.SetDataBreakpointsResponse)
+}
+
+func (c *Client) ExpectReadMemoryResponse(t *testing.T) *dap.ReadMemoryResponse {
+	t.Helper()
+	return c.expectReadProtocolMessage(t).(*dap.ReadMemoryResponse)
+}
+
+func (c *Client) ExpectDisassembleResponse(t *testing.T) *dap.DisassembleResponse {
+	t.Helper()
+	return c.expectReadProtocolMessage(t).(*dap.DisassembleResponse)
+}
+
+func (c *Client) ExpectCancelResponse(t *testing.T) *dap.CancelResponse {
+	t.Helper()
+	return c.expectReadProtocolMessage(t).(*dap.CancelResponse)
+}
+
+func (c *Client) ExpectBreakpointLocationsResponse(t *testing.T) *dap.BreakpointLocationsResponse {
+	t.Helper()
+	return c.expectReadProtocolMessage(t).(*dap.BreakpointLocationsResponse)
+}
+
+func (c *Client) ExpectModulesResponse(t *testing.T) *dap.ModulesResponse {
+	t.Helper()
+	return c.expectReadProtocolMessage(t).(*dap.ModulesResponse)
+}
+
 // InitializeRequest sends an 'initialize' request.
 func (c *Client) InitializeRequest() {
 	request := &dap.InitializeRequest{Request: *c.newRequest("initialize")}
@@ -165,6 +284,13 @@ func (c *Client) LaunchRequestWithArgs(arguments map[string]interface{}) {
 	c.send(request)
 }
 
+// AttachRequest sends an 'attach' request.
+func (c *Client) AttachRequest() {
+	request := &dap.AttachRequest{Request: *c.newRequest("attach")}
+	// TODO(polina): populate meaningful arguments
+	c.send(request)
+}
+
 // DisconnectRequest sends a 'disconnect' request.
 func (c *Client) DisconnectRequest() {
 	request := &dap.DisconnectRequest{Request: *c.newRequest("disconnect")}
@@ -207,6 +333,34 @@ func (c *Client) ContinueRequest(thread int) {
 	c.send(request)
 }
 
+// NextRequest sends a 'next' request.
+func (c *Client) NextRequest() {
+	request := &dap.NextRequest{Request: *c.newRequest("next")}
+	// TODO(polina): arguments
+	c.send(request)
+}
+
+// StepInRequest sends a 'stepIn' request.
+func (c *Client) StepInRequest() {
+	request := &dap.NextRequest{Request: *c.newRequest("stepIn")}
+	// TODO(polina): arguments
+	c.send(request)
+}
+
+// StepOutRequest sends a 'stepOut' request.
+func (c *Client) StepOutRequest() {
+	request := &dap.NextRequest{Request: *c.newRequest("stepOut")}
+	// TODO(polina): arguments
+	c.send(request)
+}
+
+// PauseRequest sends a 'pause' request.
+func (c *Client) PauseRequest() {
+	request := &dap.NextRequest{Request: *c.newRequest("pause")}
+	// TODO(polina): arguments
+	c.send(request)
+}
+
 // ThreadsRequest sends a 'threads' request.
 func (c *Client) ThreadsRequest() {
 	request := &dap.ThreadsRequest{Request: *c.newRequest("threads")}
@@ -219,6 +373,138 @@ func (c *Client) StackTraceRequest() {
 	c.send(request)
 }
 
+// ScopesRequest sends a 'scopes' request.
+func (c *Client) ScopesRequest() {
+	request := &dap.ScopesRequest{Request: *c.newRequest("scopes")}
+	c.send(request)
+}
+
+// VariablesRequest sends a 'scopes' request.
+func (c *Client) VariablesRequest() {
+	request := &dap.ScopesRequest{Request: *c.newRequest("variables")}
+	c.send(request)
+}
+
+// TeriminateRequest sends a 'terminate' request.
+func (c *Client) TerminateRequest() {
+	c.send(&dap.TerminateRequest{Request: *c.newRequest("terminate")})
+}
+
+// RestartRequest sends a 'restart' request.
+func (c *Client) RestartRequest() {
+	c.send(&dap.RestartRequest{Request: *c.newRequest("restart")})
+}
+
+// SetFunctionBreakpointsRequest sends a 'setFunctionBreakpoints' request.
+func (c *Client) SetFunctionBreakpointsRequest() {
+	c.send(&dap.SetFunctionBreakpointsRequest{Request: *c.newRequest("setFunctionBreakpoints")})
+}
+
+// StepBackRequest sends a 'stepBack' request.
+func (c *Client) StepBackRequest() {
+	c.send(&dap.StepBackRequest{Request: *c.newRequest("stepBack")})
+}
+
+// ReverseContinueRequest sends a 'reverseContinue' request.
+func (c *Client) ReverseContinueRequest() {
+	c.send(&dap.ReverseContinueRequest{Request: *c.newRequest("reverseContinue")})
+}
+
+// SetVariableRequest sends a 'setVariable' request.
+func (c *Client) SetVariableRequest() {
+	c.send(&dap.ReverseContinueRequest{Request: *c.newRequest("setVariable")})
+}
+
+// RestartFrameRequest sends a 'restartFrame' request.
+func (c *Client) RestartFrameRequest() {
+	c.send(&dap.RestartFrameRequest{Request: *c.newRequest("restartFrame")})
+}
+
+// GotoRequest sends a 'goto' request.
+func (c *Client) GotoRequest() {
+	c.send(&dap.GotoRequest{Request: *c.newRequest("goto")})
+}
+
+// SetExpressionRequest sends a 'setExpression' request.
+func (c *Client) SetExpressionRequest() {
+	c.send(&dap.SetExpressionRequest{Request: *c.newRequest("setExpression")})
+}
+
+// SourceRequest sends a 'source' request.
+func (c *Client) SourceRequest() {
+	c.send(&dap.SourceRequest{Request: *c.newRequest("source")})
+}
+
+// TerminateThreadsRequest sends a 'terminateThreads' request.
+func (c *Client) TerminateThreadsRequest() {
+	c.send(&dap.TerminateThreadsRequest{Request: *c.newRequest("terminateThreads")})
+}
+
+// EvaluateRequest sends a 'evaluate' request.
+func (c *Client) EvaluateRequest() {
+	c.send(&dap.EvaluateRequest{Request: *c.newRequest("evaluate")})
+}
+
+// StepInTargetsRequest sends a 'stepInTargets' request.
+func (c *Client) StepInTargetsRequest() {
+	c.send(&dap.StepInTargetsRequest{Request: *c.newRequest("stepInTargets")})
+}
+
+// GotoTargetsRequest sends a 'gotoTargets' request.
+func (c *Client) GotoTargetsRequest() {
+	c.send(&dap.GotoTargetsRequest{Request: *c.newRequest("gotoTargets")})
+}
+
+// CompletionsRequest sends a 'completions' request.
+func (c *Client) CompletionsRequest() {
+	c.send(&dap.CompletionsRequest{Request: *c.newRequest("completions")})
+}
+
+// ExceptionInfoRequest sends a 'exceptionInfo' request.
+func (c *Client) ExceptionInfoRequest() {
+	c.send(&dap.ExceptionInfoRequest{Request: *c.newRequest("exceptionInfo")})
+}
+
+// LoadedSourcesRequest sends a 'loadedSources' request.
+func (c *Client) LoadedSourcesRequest() {
+	c.send(&dap.LoadedSourcesRequest{Request: *c.newRequest("loadedSources")})
+}
+
+// DataBreakpointInfoRequest sends a 'dataBreakpointInfo' request.
+func (c *Client) DataBreakpointInfoRequest() {
+	c.send(&dap.DataBreakpointInfoRequest{Request: *c.newRequest("dataBreakpointInfo")})
+}
+
+// SetDataBreakpointsRequest sends a 'setDataBreakpoints' request.
+func (c *Client) SetDataBreakpointsRequest() {
+	c.send(&dap.SetDataBreakpointsRequest{Request: *c.newRequest("setDataBreakpoints")})
+}
+
+// ReadMemoryRequest sends a 'readMemory' request.
+func (c *Client) ReadMemoryRequest() {
+	c.send(&dap.ReadMemoryRequest{Request: *c.newRequest("readMemory")})
+}
+
+// DisassembleRequest sends a 'disassemble' request.
+func (c *Client) DisassembleRequest() {
+	c.send(&dap.DisassembleRequest{Request: *c.newRequest("disassemble")})
+}
+
+// CancelRequest sends a 'cancel' request.
+func (c *Client) CancelRequest() {
+	c.send(&dap.CancelRequest{Request: *c.newRequest("cancel")})
+}
+
+// BreakpointLocationsRequest sends a 'breakpointLocations' request.
+func (c *Client) BreakpointLocationsRequest() {
+	c.send(&dap.BreakpointLocationsRequest{Request: *c.newRequest("breakpointLocations")})
+}
+
+// ModulesRequest sends a 'modules' request.
+func (c *Client) ModulesRequest() {
+	c.send(&dap.ModulesRequest{Request: *c.newRequest("modules")})
+}
+
 // UnknownRequest triggers dap.DecodeProtocolMessageFieldError.
 func (c *Client) UnknownRequest() {
 	request := c.newRequest("unknown")
diff --git a/service/dap/server_test.go b/service/dap/server_test.go
index f578676c..2577419e 100644
--- a/service/dap/server_test.go
+++ b/service/dap/server_test.go
@@ -168,15 +168,15 @@ func TestStopOnEntry(t *testing.T) {
 		// 8 >> stackTrace, << stackTrace
 		client.StackTraceRequest()
 		stResp := client.ExpectErrorResponse(t)
-		if stResp.Seq != 0 || stResp.RequestSeq != 8 || stResp.Message != "Unsupported command" {
-			t.Errorf("\ngot %#v\nwant Seq=0, RequestSeq=8 Message=\"Unsupported command\"", stResp)
+		if stResp.Seq != 0 || stResp.RequestSeq != 8 || stResp.Message != "Not yet implemented" {
+			t.Errorf("\ngot %#v\nwant Seq=0, RequestSeq=8 Message=\"Not yet implemented\"", stResp)
 		}
 
 		// 9 >> stackTrace, << stackTrace
 		client.StackTraceRequest()
 		stResp = client.ExpectErrorResponse(t)
-		if stResp.Seq != 0 || stResp.RequestSeq != 9 || stResp.Message != "Unsupported command" {
-			t.Errorf("\ngot %#v\nwant Seq=0, RequestSeq=9 Message=\"Unsupported command\"", stResp)
+		if stResp.Seq != 0 || stResp.RequestSeq != 9 || stResp.Message != "Not yet implemented" {
+			t.Errorf("\ngot %#v\nwant Seq=0, RequestSeq=9 Message=\"Not yet implemented\"", stResp)
 		}
 
 		// 10 >> continue, << continue, << terminated
@@ -366,6 +366,147 @@ func TestLaunchTestRequest(t *testing.T) {
 	})
 }
 
+func TestUnupportedCommandResponses(t *testing.T) {
+	var got *dap.ErrorResponse
+	runTest(t, "increment", func(client *daptest.Client, fixture protest.Fixture) {
+		seqCnt := 1
+		expectUnsupportedCommand := func(cmd string) {
+			t.Helper()
+			got = client.ExpectUnsupportedCommandErrorResponse(t)
+			if got.RequestSeq != seqCnt || got.Command != cmd {
+				t.Errorf("\ngot  %#v\nwant RequestSeq=%d Command=%s", got, seqCnt, cmd)
+			}
+			seqCnt++
+		}
+
+		client.RestartFrameRequest()
+		expectUnsupportedCommand("restartFrame")
+
+		client.GotoRequest()
+		expectUnsupportedCommand("goto")
+
+		client.SourceRequest()
+		expectUnsupportedCommand("source")
+
+		client.TerminateThreadsRequest()
+		expectUnsupportedCommand("terminateThreads")
+
+		client.StepInTargetsRequest()
+		expectUnsupportedCommand("stepInTargets")
+
+		client.GotoTargetsRequest()
+		expectUnsupportedCommand("gotoTargets")
+
+		client.CompletionsRequest()
+		expectUnsupportedCommand("completions")
+
+		client.ExceptionInfoRequest()
+		expectUnsupportedCommand("exceptionInfo")
+
+		client.DataBreakpointInfoRequest()
+		expectUnsupportedCommand("dataBreakpointInfo")
+
+		client.SetDataBreakpointsRequest()
+		expectUnsupportedCommand("setDataBreakpoints")
+
+		client.BreakpointLocationsRequest()
+		expectUnsupportedCommand("breakpointLocations")
+
+		client.ModulesRequest()
+		expectUnsupportedCommand("modules")
+	})
+}
+
+func TestRequiredNotYetImplementedResponses(t *testing.T) {
+	var got *dap.ErrorResponse
+	runTest(t, "increment", func(client *daptest.Client, fixture protest.Fixture) {
+		seqCnt := 1
+		expectNotYetImplemented := func(cmd string) {
+			t.Helper()
+			got = client.ExpectNotYetImplementedErrorResponse(t)
+			if got.RequestSeq != seqCnt || got.Command != cmd {
+				t.Errorf("\ngot  %#v\nwant RequestSeq=%d Command=%s", got, seqCnt, cmd)
+			}
+			seqCnt++
+		}
+
+		client.AttachRequest()
+		expectNotYetImplemented("attach")
+
+		client.NextRequest()
+		expectNotYetImplemented("next")
+
+		client.StepInRequest()
+		expectNotYetImplemented("stepIn")
+
+		client.StepOutRequest()
+		expectNotYetImplemented("stepOut")
+
+		client.PauseRequest()
+		expectNotYetImplemented("pause")
+
+		client.StackTraceRequest()
+		expectNotYetImplemented("stackTrace")
+
+		client.ScopesRequest()
+		expectNotYetImplemented("scopes")
+
+		client.VariablesRequest()
+		expectNotYetImplemented("variables")
+
+		client.EvaluateRequest()
+		expectNotYetImplemented("evaluate")
+	})
+}
+
+func TestOptionalNotYetImplementedResponses(t *testing.T) {
+	var got *dap.ErrorResponse
+	runTest(t, "increment", func(client *daptest.Client, fixture protest.Fixture) {
+		seqCnt := 1
+		expectNotYetImplemented := func(cmd string) {
+			t.Helper()
+			got = client.ExpectNotYetImplementedErrorResponse(t)
+			if got.RequestSeq != seqCnt || got.Command != cmd {
+				t.Errorf("\ngot  %#v\nwant RequestSeq=%d Command=%s", got, seqCnt, cmd)
+			}
+			seqCnt++
+		}
+
+		client.TerminateRequest()
+		expectNotYetImplemented("terminate")
+
+		client.RestartRequest()
+		expectNotYetImplemented("restart")
+
+		client.SetFunctionBreakpointsRequest()
+		expectNotYetImplemented("setFunctionBreakpoints")
+
+		client.StepBackRequest()
+		expectNotYetImplemented("stepBack")
+
+		client.ReverseContinueRequest()
+		expectNotYetImplemented("reverseContinue")
+
+		client.SetVariableRequest()
+		expectNotYetImplemented("setVariable")
+
+		client.SetExpressionRequest()
+		expectNotYetImplemented("setExpression")
+
+		client.LoadedSourcesRequest()
+		expectNotYetImplemented("loadedSources")
+
+		client.ReadMemoryRequest()
+		expectNotYetImplemented("readMemory")
+
+		client.DisassembleRequest()
+		expectNotYetImplemented("disassemble")
+
+		client.CancelRequest()
+		expectNotYetImplemented("cancel")
+	})
+}
+
 func TestBadLaunchRequests(t *testing.T) {
 	runTest(t, "increment", func(client *daptest.Client, fixture protest.Fixture) {
 		seqCnt := 1