81 lines
2.9 KiB
C++
81 lines
2.9 KiB
C++
|
|
// Step 1920: LSPRequestThrottler
|
||
|
|
// Debounces per-URI requests to prevent flooding language servers.
|
||
|
|
//
|
||
|
|
// t1: no prior record → shouldAllow true
|
||
|
|
// t2: within debounce window → shouldAllow false
|
||
|
|
// t3: after debounce window expires → shouldAllow true
|
||
|
|
// t4: reset clears uri; resetAll clears everything
|
||
|
|
// t5: lastTimestamp returns -1 for missing, correct value after record
|
||
|
|
|
||
|
|
#include "LSPRequestThrottler.h"
|
||
|
|
#include <iostream>
|
||
|
|
|
||
|
|
namespace ws = whetstone;
|
||
|
|
|
||
|
|
static int p=0,f=0;
|
||
|
|
#define T(n) { std::cout<<" "<<#n<<"... "; }
|
||
|
|
#define P() { std::cout<<"PASS\n"; ++p; }
|
||
|
|
#define F(m) { std::cout<<"FAIL: "<<m<<"\n"; ++f; }
|
||
|
|
#define C(c,m) if(!(c)){F(m);return;}
|
||
|
|
|
||
|
|
void t1(){
|
||
|
|
T(no_prior_record_allows);
|
||
|
|
ws::LSPRequestThrottler t;
|
||
|
|
C(t.shouldAllow("file:///a.go","textDocument/didChange",1000,500), "no record allows");
|
||
|
|
P();
|
||
|
|
}
|
||
|
|
|
||
|
|
void t2(){
|
||
|
|
T(within_debounce_window_blocks);
|
||
|
|
ws::LSPRequestThrottler t;
|
||
|
|
t.record("file:///a.go","textDocument/didChange",1000);
|
||
|
|
// 200ms later, 500ms debounce → block
|
||
|
|
C(!t.shouldAllow("file:///a.go","textDocument/didChange",1200,500), "within window blocked");
|
||
|
|
// different method: not throttled
|
||
|
|
C( t.shouldAllow("file:///a.go","textDocument/hover",1200,500), "different method allowed");
|
||
|
|
// different uri: not throttled
|
||
|
|
C( t.shouldAllow("file:///b.go","textDocument/didChange",1200,500), "different uri allowed");
|
||
|
|
P();
|
||
|
|
}
|
||
|
|
|
||
|
|
void t3(){
|
||
|
|
T(after_debounce_window_allows);
|
||
|
|
ws::LSPRequestThrottler t;
|
||
|
|
t.record("file:///a.go","textDocument/didChange",1000);
|
||
|
|
// exactly at boundary: 1000+500=1500 → allow (>=)
|
||
|
|
C( t.shouldAllow("file:///a.go","textDocument/didChange",1500,500), "at boundary allowed");
|
||
|
|
// past boundary
|
||
|
|
C( t.shouldAllow("file:///a.go","textDocument/didChange",1600,500), "past boundary allowed");
|
||
|
|
P();
|
||
|
|
}
|
||
|
|
|
||
|
|
void t4(){
|
||
|
|
T(reset_and_resetAll);
|
||
|
|
ws::LSPRequestThrottler t;
|
||
|
|
t.record("file:///a.go","textDocument/didChange",1000);
|
||
|
|
t.record("file:///b.go","textDocument/didChange",1000);
|
||
|
|
t.reset("file:///a.go");
|
||
|
|
C( t.shouldAllow("file:///a.go","textDocument/didChange",1100,500), "a.go reset → allowed");
|
||
|
|
C(!t.shouldAllow("file:///b.go","textDocument/didChange",1100,500), "b.go still throttled");
|
||
|
|
t.resetAll();
|
||
|
|
C( t.shouldAllow("file:///b.go","textDocument/didChange",1100,500), "b.go allowed after resetAll");
|
||
|
|
P();
|
||
|
|
}
|
||
|
|
|
||
|
|
void t5(){
|
||
|
|
T(lastTimestamp);
|
||
|
|
ws::LSPRequestThrottler t;
|
||
|
|
C(t.lastTimestamp("file:///a.go","textDocument/didChange") == -1, "no record returns -1");
|
||
|
|
t.record("file:///a.go","textDocument/didChange",9999);
|
||
|
|
C(t.lastTimestamp("file:///a.go","textDocument/didChange") == 9999, "correct timestamp");
|
||
|
|
C(t.lastTimestamp("file:///a.go","textDocument/hover") == -1, "different method -1");
|
||
|
|
P();
|
||
|
|
}
|
||
|
|
|
||
|
|
int main(){
|
||
|
|
std::cout << "Step 1920: LSPRequestThrottler\n";
|
||
|
|
t1(); t2(); t3(); t4(); t5();
|
||
|
|
std::cout << "\n" << p << "/" << (p+f) << " passed\n";
|
||
|
|
return f > 0 ? 1 : 0;
|
||
|
|
}
|