Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/debug/test/common/mockDebug.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { DeferredPromise } from '../../../../../base/common/async.js';
7
import { CancellationToken } from '../../../../../base/common/cancellation.js';
8
import { Event } from '../../../../../base/common/event.js';
9
import { URI as uri } from '../../../../../base/common/uri.js';
10
import { IPosition, Position } from '../../../../../editor/common/core/position.js';
11
import { ITextModel } from '../../../../../editor/common/model.js';
12
import { NullLogService } from '../../../../../platform/log/common/log.js';
13
import { IStorageService } from '../../../../../platform/storage/common/storage.js';
14
import { IWorkspaceFolder } from '../../../../../platform/workspace/common/workspace.js';
15
import { AbstractDebugAdapter } from '../../common/abstractDebugAdapter.js';
16
import { AdapterEndEvent, IAdapterManager, IBreakpoint, IBreakpointData, IBreakpointUpdateData, IConfig, IConfigurationManager, IDataBreakpoint, IDataBreakpointInfoResponse, IDebugLocationReferenced, IDebugModel, IDebugService, IDebugSession, IDebugSessionOptions, IDebugger, IExceptionBreakpoint, IExceptionInfo, IFunctionBreakpoint, IInstructionBreakpoint, ILaunch, IMemoryRegion, INewReplElementData, IRawModelUpdate, IRawStoppedDetails, IReplElement, IStackFrame, IThread, IViewModel, LoadedSourceEvent, State } from '../../common/debug.js';
17
import { DebugCompoundRoot } from '../../common/debugCompoundRoot.js';
18
import { IInstructionBreakpointOptions } from '../../common/debugModel.js';
19
import { Source } from '../../common/debugSource.js';
20
import { DebugStorage } from '../../common/debugStorage.js';
21
22
export class MockDebugService implements IDebugService {
23
_serviceBrand: undefined;
24
25
get state(): State {
26
throw new Error('not implemented');
27
}
28
29
get onWillNewSession(): Event<IDebugSession> {
30
throw new Error('not implemented');
31
}
32
33
get onDidNewSession(): Event<IDebugSession> {
34
throw new Error('not implemented');
35
}
36
37
get onDidEndSession(): Event<{ session: IDebugSession; restart: boolean }> {
38
throw new Error('not implemented');
39
}
40
41
get onDidChangeState(): Event<State> {
42
throw new Error('not implemented');
43
}
44
45
getConfigurationManager(): IConfigurationManager {
46
throw new Error('not implemented');
47
}
48
49
getAdapterManager(): IAdapterManager {
50
throw new Error('Method not implemented.');
51
}
52
53
canSetBreakpointsIn(model: ITextModel): boolean {
54
throw new Error('Method not implemented.');
55
}
56
57
focusStackFrame(focusedStackFrame: IStackFrame): Promise<void> {
58
throw new Error('not implemented');
59
}
60
61
sendAllBreakpoints(session?: IDebugSession): Promise<any> {
62
throw new Error('not implemented');
63
}
64
65
sendBreakpoints(modelUri: uri, sourceModified?: boolean | undefined, session?: IDebugSession | undefined): Promise<any> {
66
throw new Error('not implemented');
67
}
68
69
addBreakpoints(uri: uri, rawBreakpoints: IBreakpointData[]): Promise<IBreakpoint[]> {
70
throw new Error('not implemented');
71
}
72
73
updateBreakpoints(uri: uri, data: Map<string, IBreakpointUpdateData>, sendOnResourceSaved: boolean): Promise<void> {
74
throw new Error('not implemented');
75
}
76
77
enableOrDisableBreakpoints(enabled: boolean): Promise<void> {
78
throw new Error('not implemented');
79
}
80
81
setBreakpointsActivated(): Promise<void> {
82
throw new Error('not implemented');
83
}
84
85
removeBreakpoints(): Promise<any> {
86
throw new Error('not implemented');
87
}
88
89
addInstructionBreakpoint(opts: IInstructionBreakpointOptions): Promise<void> {
90
throw new Error('Method not implemented.');
91
}
92
93
removeInstructionBreakpoints(address?: string): Promise<void> {
94
throw new Error('Method not implemented.');
95
}
96
97
setExceptionBreakpointCondition(breakpoint: IExceptionBreakpoint, condition: string): Promise<void> {
98
throw new Error('Method not implemented.');
99
}
100
101
setExceptionBreakpointsForSession(session: IDebugSession, data: DebugProtocol.ExceptionBreakpointsFilter[]): void {
102
throw new Error('Method not implemented.');
103
}
104
105
addFunctionBreakpoint(): void { }
106
107
moveWatchExpression(id: string, position: number): void { }
108
109
updateFunctionBreakpoint(id: string, update: { name?: string; hitCondition?: string; condition?: string }): Promise<void> {
110
throw new Error('not implemented');
111
}
112
113
removeFunctionBreakpoints(id?: string): Promise<void> {
114
throw new Error('not implemented');
115
}
116
117
addDataBreakpoint(): Promise<void> {
118
throw new Error('Method not implemented.');
119
}
120
121
updateDataBreakpoint(id: string, update: { hitCondition?: string; condition?: string }): Promise<void> {
122
throw new Error('not implemented');
123
}
124
125
removeDataBreakpoints(id?: string | undefined): Promise<void> {
126
throw new Error('Method not implemented.');
127
}
128
129
addReplExpression(name: string): Promise<void> {
130
throw new Error('not implemented');
131
}
132
133
removeReplExpressions(): void { }
134
135
addWatchExpression(name?: string): Promise<void> {
136
throw new Error('not implemented');
137
}
138
139
renameWatchExpression(id: string, newName: string): Promise<void> {
140
throw new Error('not implemented');
141
}
142
143
removeWatchExpressions(id?: string): void { }
144
145
startDebugging(launch: ILaunch, configOrName?: IConfig | string, options?: IDebugSessionOptions): Promise<boolean> {
146
return Promise.resolve(true);
147
}
148
149
restartSession(): Promise<any> {
150
throw new Error('not implemented');
151
}
152
153
stopSession(): Promise<any> {
154
throw new Error('not implemented');
155
}
156
157
getModel(): IDebugModel {
158
throw new Error('not implemented');
159
}
160
161
getViewModel(): IViewModel {
162
throw new Error('not implemented');
163
}
164
165
sourceIsNotAvailable(uri: uri): void { }
166
167
tryToAutoFocusStackFrame(thread: IThread): Promise<any> {
168
throw new Error('not implemented');
169
}
170
171
runTo(uri: uri, lineNumber: number, column?: number): Promise<void> {
172
throw new Error('Method not implemented.');
173
}
174
}
175
176
export class MockSession implements IDebugSession {
177
readonly suppressDebugToolbar = false;
178
readonly suppressDebugStatusbar = false;
179
readonly suppressDebugView = false;
180
readonly autoExpandLazyVariables = false;
181
182
dispose(): void {
183
184
}
185
186
getMemory(memoryReference: string): IMemoryRegion {
187
throw new Error('Method not implemented.');
188
}
189
190
get onDidInvalidateMemory(): Event<DebugProtocol.MemoryEvent> {
191
throw new Error('Not implemented');
192
}
193
194
readMemory(memoryReference: string, offset: number, count: number): Promise<DebugProtocol.ReadMemoryResponse | undefined> {
195
throw new Error('Method not implemented.');
196
}
197
198
writeMemory(memoryReference: string, offset: number, data: string, allowPartial?: boolean): Promise<DebugProtocol.WriteMemoryResponse | undefined> {
199
throw new Error('Method not implemented.');
200
}
201
202
cancelCorrelatedTestRun(): void {
203
204
}
205
206
get compoundRoot(): DebugCompoundRoot | undefined {
207
return undefined;
208
}
209
210
get saveBeforeRestart(): boolean {
211
return true;
212
}
213
214
get isSimpleUI(): boolean {
215
return false;
216
}
217
218
get lifecycleManagedByParent(): boolean {
219
return false;
220
}
221
222
stepInTargets(frameId: number): Promise<{ id: number; label: string }[]> {
223
throw new Error('Method not implemented.');
224
}
225
226
cancel(_progressId: string): Promise<DebugProtocol.CancelResponse> {
227
throw new Error('Method not implemented.');
228
}
229
230
breakpointsLocations(uri: uri, lineNumber: number): Promise<IPosition[]> {
231
throw new Error('Method not implemented.');
232
}
233
234
dataBytesBreakpointInfo(address: string, bytes: number): Promise<IDataBreakpointInfoResponse | undefined> {
235
throw new Error('Method not implemented.');
236
}
237
238
dataBreakpointInfo(name: string, variablesReference?: number | undefined): Promise<{ dataId: string | null; description: string; canPersist?: boolean | undefined } | undefined> {
239
throw new Error('Method not implemented.');
240
}
241
242
sendDataBreakpoints(dbps: IDataBreakpoint[]): Promise<void> {
243
throw new Error('Method not implemented.');
244
}
245
246
subId: string | undefined;
247
248
get compact(): boolean {
249
return false;
250
}
251
252
setSubId(subId: string | undefined): void {
253
throw new Error('Method not implemented.');
254
}
255
256
get parentSession(): IDebugSession | undefined {
257
return undefined;
258
}
259
260
getReplElements(): IReplElement[] {
261
return [];
262
}
263
264
hasSeparateRepl(): boolean {
265
return true;
266
}
267
268
removeReplExpressions(): void { }
269
get onDidChangeReplElements(): Event<IReplElement | undefined> {
270
throw new Error('not implemented');
271
}
272
273
addReplExpression(stackFrame: IStackFrame, name: string): Promise<void> {
274
return Promise.resolve(undefined);
275
}
276
277
appendToRepl(data: INewReplElementData): void { }
278
279
configuration: IConfig = { type: 'mock', name: 'mock', request: 'launch' };
280
unresolvedConfiguration: IConfig = { type: 'mock', name: 'mock', request: 'launch' };
281
state = State.Stopped;
282
root!: IWorkspaceFolder;
283
capabilities: DebugProtocol.Capabilities = {};
284
285
getId(): string {
286
return 'mock';
287
}
288
289
getLabel(): string {
290
return 'mockname';
291
}
292
293
get name(): string {
294
return 'mockname';
295
}
296
297
setName(name: string): void {
298
throw new Error('not implemented');
299
}
300
301
getSourceForUri(modelUri: uri): Source {
302
throw new Error('not implemented');
303
}
304
305
getThread(threadId: number): IThread {
306
throw new Error('not implemented');
307
}
308
309
getStoppedDetails(): IRawStoppedDetails {
310
throw new Error('not implemented');
311
}
312
313
get onDidCustomEvent(): Event<DebugProtocol.Event> {
314
throw new Error('not implemented');
315
}
316
317
get onDidLoadedSource(): Event<LoadedSourceEvent> {
318
throw new Error('not implemented');
319
}
320
321
get onDidChangeState(): Event<void> {
322
throw new Error('not implemented');
323
}
324
325
get onDidEndAdapter(): Event<AdapterEndEvent | undefined> {
326
throw new Error('not implemented');
327
}
328
329
get onDidChangeName(): Event<string> {
330
throw new Error('not implemented');
331
}
332
333
get onDidProgressStart(): Event<DebugProtocol.ProgressStartEvent> {
334
throw new Error('not implemented');
335
}
336
337
get onDidProgressUpdate(): Event<DebugProtocol.ProgressUpdateEvent> {
338
throw new Error('not implemented');
339
}
340
341
get onDidProgressEnd(): Event<DebugProtocol.ProgressEndEvent> {
342
throw new Error('not implemented');
343
}
344
345
setConfiguration(configuration: { resolved: IConfig; unresolved: IConfig }) { }
346
347
getAllThreads(): IThread[] {
348
return [];
349
}
350
351
getSource(raw: DebugProtocol.Source): Source {
352
throw new Error('not implemented');
353
}
354
355
getLoadedSources(): Promise<Source[]> {
356
return Promise.resolve([]);
357
}
358
359
completions(frameId: number, threadId: number, text: string, position: Position): Promise<DebugProtocol.CompletionsResponse> {
360
throw new Error('not implemented');
361
}
362
363
clearThreads(removeThreads: boolean, reference?: number): void { }
364
365
rawUpdate(data: IRawModelUpdate): void { }
366
367
initialize(dbgr: IDebugger): Promise<void> {
368
throw new Error('Method not implemented.');
369
}
370
launchOrAttach(config: IConfig): Promise<void> {
371
throw new Error('Method not implemented.');
372
}
373
restart(): Promise<void> {
374
throw new Error('Method not implemented.');
375
}
376
sendBreakpoints(modelUri: uri, bpts: IBreakpoint[], sourceModified: boolean): Promise<void> {
377
throw new Error('Method not implemented.');
378
}
379
sendFunctionBreakpoints(fbps: IFunctionBreakpoint[]): Promise<void> {
380
throw new Error('Method not implemented.');
381
}
382
sendExceptionBreakpoints(exbpts: IExceptionBreakpoint[]): Promise<void> {
383
throw new Error('Method not implemented.');
384
}
385
sendInstructionBreakpoints(dbps: IInstructionBreakpoint[]): Promise<void> {
386
throw new Error('Method not implemented.');
387
}
388
getDebugProtocolBreakpoint(breakpointId: string): DebugProtocol.Breakpoint | undefined {
389
throw new Error('Method not implemented.');
390
}
391
customRequest(request: string, args: any): Promise<DebugProtocol.Response> {
392
throw new Error('Method not implemented.');
393
}
394
stackTrace(threadId: number, startFrame: number, levels: number, token: CancellationToken): Promise<DebugProtocol.StackTraceResponse> {
395
throw new Error('Method not implemented.');
396
}
397
exceptionInfo(threadId: number): Promise<IExceptionInfo> {
398
throw new Error('Method not implemented.');
399
}
400
scopes(frameId: number): Promise<DebugProtocol.ScopesResponse> {
401
throw new Error('Method not implemented.');
402
}
403
variables(variablesReference: number, threadId: number | undefined, filter: 'indexed' | 'named', start: number, count: number): Promise<DebugProtocol.VariablesResponse> {
404
throw new Error('Method not implemented.');
405
}
406
evaluate(expression: string, frameId: number, context?: string): Promise<DebugProtocol.EvaluateResponse> {
407
throw new Error('Method not implemented.');
408
}
409
restartFrame(frameId: number, threadId: number): Promise<void> {
410
throw new Error('Method not implemented.');
411
}
412
next(threadId: number, granularity?: DebugProtocol.SteppingGranularity): Promise<void> {
413
throw new Error('Method not implemented.');
414
}
415
stepIn(threadId: number, targetId?: number, granularity?: DebugProtocol.SteppingGranularity): Promise<void> {
416
throw new Error('Method not implemented.');
417
}
418
stepOut(threadId: number, granularity?: DebugProtocol.SteppingGranularity): Promise<void> {
419
throw new Error('Method not implemented.');
420
}
421
stepBack(threadId: number, granularity?: DebugProtocol.SteppingGranularity): Promise<void> {
422
throw new Error('Method not implemented.');
423
}
424
continue(threadId: number): Promise<void> {
425
throw new Error('Method not implemented.');
426
}
427
reverseContinue(threadId: number): Promise<void> {
428
throw new Error('Method not implemented.');
429
}
430
pause(threadId: number): Promise<void> {
431
throw new Error('Method not implemented.');
432
}
433
terminateThreads(threadIds: number[]): Promise<void> {
434
throw new Error('Method not implemented.');
435
}
436
setVariable(variablesReference: number, name: string, value: string): Promise<DebugProtocol.SetVariableResponse> {
437
throw new Error('Method not implemented.');
438
}
439
setExpression(frameId: number, expression: string, value: string): Promise<DebugProtocol.SetExpressionResponse | undefined> {
440
throw new Error('Method not implemented.');
441
}
442
loadSource(resource: uri): Promise<DebugProtocol.SourceResponse> {
443
throw new Error('Method not implemented.');
444
}
445
disassemble(memoryReference: string, offset: number, instructionOffset: number, instructionCount: number): Promise<DebugProtocol.DisassembledInstruction[] | undefined> {
446
throw new Error('Method not implemented.');
447
}
448
449
terminate(restart = false): Promise<void> {
450
throw new Error('Method not implemented.');
451
}
452
disconnect(restart = false): Promise<void> {
453
throw new Error('Method not implemented.');
454
}
455
456
gotoTargets(source: DebugProtocol.Source, line: number, column?: number | undefined): Promise<DebugProtocol.GotoTargetsResponse> {
457
throw new Error('Method not implemented.');
458
}
459
goto(threadId: number, targetId: number): Promise<DebugProtocol.GotoResponse> {
460
throw new Error('Method not implemented.');
461
}
462
resolveLocationReference(locationReference: number): Promise<IDebugLocationReferenced> {
463
throw new Error('Method not implemented.');
464
}
465
}
466
467
export class MockRawSession {
468
469
capabilities: DebugProtocol.Capabilities = {};
470
disconnected = false;
471
sessionLengthInSeconds: number = 0;
472
473
readyForBreakpoints = true;
474
emittedStopped = true;
475
476
getLengthInSeconds(): number {
477
return 100;
478
}
479
480
stackTrace(args: DebugProtocol.StackTraceArguments): Promise<DebugProtocol.StackTraceResponse> {
481
return Promise.resolve({
482
seq: 1,
483
type: 'response',
484
request_seq: 1,
485
success: true,
486
command: 'stackTrace',
487
body: {
488
stackFrames: [{
489
id: 1,
490
name: 'mock',
491
line: 5,
492
column: 6
493
}]
494
}
495
});
496
}
497
498
exceptionInfo(args: DebugProtocol.ExceptionInfoArguments): Promise<DebugProtocol.ExceptionInfoResponse> {
499
throw new Error('not implemented');
500
}
501
502
launchOrAttach(args: IConfig): Promise<DebugProtocol.Response> {
503
throw new Error('not implemented');
504
}
505
506
scopes(args: DebugProtocol.ScopesArguments): Promise<DebugProtocol.ScopesResponse> {
507
throw new Error('not implemented');
508
}
509
510
variables(args: DebugProtocol.VariablesArguments): Promise<DebugProtocol.VariablesResponse> {
511
throw new Error('not implemented');
512
}
513
514
evaluate(args: DebugProtocol.EvaluateArguments): Promise<DebugProtocol.EvaluateResponse> {
515
return Promise.resolve(null!);
516
}
517
518
custom(request: string, args: any): Promise<DebugProtocol.Response> {
519
throw new Error('not implemented');
520
}
521
522
terminate(restart = false): Promise<DebugProtocol.TerminateResponse> {
523
throw new Error('not implemented');
524
}
525
526
disconnect(restart?: boolean): Promise<any> {
527
throw new Error('not implemented');
528
}
529
530
threads(): Promise<DebugProtocol.ThreadsResponse> {
531
throw new Error('not implemented');
532
}
533
534
stepIn(args: DebugProtocol.StepInArguments): Promise<DebugProtocol.StepInResponse> {
535
throw new Error('not implemented');
536
}
537
538
stepOut(args: DebugProtocol.StepOutArguments): Promise<DebugProtocol.StepOutResponse> {
539
throw new Error('not implemented');
540
}
541
542
stepBack(args: DebugProtocol.StepBackArguments): Promise<DebugProtocol.StepBackResponse> {
543
throw new Error('not implemented');
544
}
545
546
continue(args: DebugProtocol.ContinueArguments): Promise<DebugProtocol.ContinueResponse> {
547
throw new Error('not implemented');
548
}
549
550
reverseContinue(args: DebugProtocol.ReverseContinueArguments): Promise<DebugProtocol.ReverseContinueResponse> {
551
throw new Error('not implemented');
552
}
553
554
pause(args: DebugProtocol.PauseArguments): Promise<DebugProtocol.PauseResponse> {
555
throw new Error('not implemented');
556
}
557
558
terminateThreads(args: DebugProtocol.TerminateThreadsArguments): Promise<DebugProtocol.TerminateThreadsResponse> {
559
throw new Error('not implemented');
560
}
561
562
setVariable(args: DebugProtocol.SetVariableArguments): Promise<DebugProtocol.SetVariableResponse> {
563
throw new Error('not implemented');
564
}
565
566
restartFrame(args: DebugProtocol.RestartFrameArguments): Promise<DebugProtocol.RestartFrameResponse> {
567
throw new Error('not implemented');
568
}
569
570
completions(args: DebugProtocol.CompletionsArguments): Promise<DebugProtocol.CompletionsResponse> {
571
throw new Error('not implemented');
572
}
573
574
next(args: DebugProtocol.NextArguments): Promise<DebugProtocol.NextResponse> {
575
throw new Error('not implemented');
576
}
577
578
source(args: DebugProtocol.SourceArguments): Promise<DebugProtocol.SourceResponse> {
579
throw new Error('not implemented');
580
}
581
582
loadedSources(args: DebugProtocol.LoadedSourcesArguments): Promise<DebugProtocol.LoadedSourcesResponse> {
583
throw new Error('not implemented');
584
}
585
586
setBreakpoints(args: DebugProtocol.SetBreakpointsArguments): Promise<DebugProtocol.SetBreakpointsResponse> {
587
throw new Error('not implemented');
588
}
589
590
setFunctionBreakpoints(args: DebugProtocol.SetFunctionBreakpointsArguments): Promise<DebugProtocol.SetFunctionBreakpointsResponse> {
591
throw new Error('not implemented');
592
}
593
594
setExceptionBreakpoints(args: DebugProtocol.SetExceptionBreakpointsArguments): Promise<DebugProtocol.SetExceptionBreakpointsResponse> {
595
throw new Error('not implemented');
596
}
597
598
readonly onDidStop: Event<DebugProtocol.StoppedEvent> = null!;
599
}
600
601
export class MockDebugAdapter extends AbstractDebugAdapter {
602
private seq = 0;
603
604
private pendingResponses = new Map<string, DeferredPromise<DebugProtocol.Response>>();
605
606
startSession(): Promise<void> {
607
return Promise.resolve();
608
}
609
610
stopSession(): Promise<void> {
611
return Promise.resolve();
612
}
613
614
sendMessage(message: DebugProtocol.ProtocolMessage): void {
615
if (message.type === 'request') {
616
setTimeout(() => {
617
const request = message as DebugProtocol.Request;
618
switch (request.command) {
619
case 'evaluate':
620
this.evaluate(request, request.arguments);
621
return;
622
}
623
this.sendResponseBody(request, {});
624
return;
625
}, 0);
626
} else if (message.type === 'response') {
627
const response = message as DebugProtocol.Response;
628
if (this.pendingResponses.has(response.command)) {
629
this.pendingResponses.get(response.command)!.complete(response);
630
}
631
}
632
}
633
634
sendResponseBody(request: DebugProtocol.Request, body: any) {
635
const response: DebugProtocol.Response = {
636
seq: ++this.seq,
637
type: 'response',
638
request_seq: request.seq,
639
command: request.command,
640
success: true,
641
body
642
};
643
this.acceptMessage(response);
644
}
645
646
sendEventBody(event: string, body: any) {
647
const response: DebugProtocol.Event = {
648
seq: ++this.seq,
649
type: 'event',
650
event,
651
body
652
};
653
this.acceptMessage(response);
654
}
655
656
waitForResponseFromClient(command: string): Promise<DebugProtocol.Response> {
657
const deferred = new DeferredPromise<DebugProtocol.Response>();
658
if (this.pendingResponses.has(command)) {
659
return this.pendingResponses.get(command)!.p;
660
}
661
662
this.pendingResponses.set(command, deferred);
663
return deferred.p;
664
}
665
666
sendRequestBody(command: string, args: any) {
667
const response: DebugProtocol.Request = {
668
seq: ++this.seq,
669
type: 'request',
670
command,
671
arguments: args
672
};
673
this.acceptMessage(response);
674
}
675
676
evaluate(request: DebugProtocol.Request, args: DebugProtocol.EvaluateArguments) {
677
if (args.expression.indexOf('before.') === 0) {
678
this.sendEventBody('output', { output: args.expression });
679
}
680
681
this.sendResponseBody(request, {
682
result: '=' + args.expression,
683
variablesReference: 0
684
});
685
686
if (args.expression.indexOf('after.') === 0) {
687
this.sendEventBody('output', { output: args.expression });
688
}
689
}
690
}
691
692
export class MockDebugStorage extends DebugStorage {
693
694
constructor(storageService: IStorageService) {
695
super(storageService, undefined as any, undefined as any, new NullLogService());
696
}
697
}
698
699