@@ -12,7 +12,11 @@ import * as api from "./api-client";
1212import * as diffUtils from "./diff-informed-analysis-utils" ;
1313import { Logger } from "./logging" ;
1414import * as sarif from "./sarif" ;
15- import { RecordingLogger , setupTests } from "./testing-utils" ;
15+ import {
16+ checkExpectedLogMessages ,
17+ RecordingLogger ,
18+ setupTests ,
19+ } from "./testing-utils" ;
1620import * as uploadLib from "./upload-lib" ;
1721import { UploadPayload } from "./upload-lib/types" ;
1822import { GitHubVariant , initializeEnvironment , withTmpDir } from "./util" ;
@@ -1014,12 +1018,62 @@ for (const analysisKind of analyses.supportedAnalysisKinds) {
10141018 ) ;
10151019}
10161020
1021+ function createMockSarifWithResults (
1022+ results : sarif . Result [ ] ,
1023+ ) : Partial < sarif . Log > {
1024+ return {
1025+ version : "2.1.0" ,
1026+ runs : [
1027+ {
1028+ tool : {
1029+ driver : {
1030+ name : "test tool" ,
1031+ } ,
1032+ } ,
1033+ results,
1034+ } ,
1035+ ] ,
1036+ } ;
1037+ }
1038+
1039+ function createMockResultWithUri (
1040+ uri : string ,
1041+ startLine = 2 ,
1042+ relatedUri ?: string ,
1043+ ) : sarif . Result {
1044+ return {
1045+ ruleId : "test-rule" ,
1046+ message : { text : "test message" } ,
1047+ locations : [
1048+ {
1049+ physicalLocation : {
1050+ artifactLocation : { uri } ,
1051+ region : { startLine } ,
1052+ } ,
1053+ } ,
1054+ ] ,
1055+ ...( relatedUri
1056+ ? {
1057+ relatedLocations : [
1058+ {
1059+ physicalLocation : {
1060+ artifactLocation : { uri : relatedUri } ,
1061+ region : { startLine } ,
1062+ } ,
1063+ } ,
1064+ ] ,
1065+ }
1066+ : { } ) ,
1067+ } ;
1068+ }
1069+
10171070function runFilterAlertsByDiffRange (
10181071 input : Partial < sarif . Log > ,
10191072 diffRanges : diffUtils . DiffThunkRange [ ] ,
1073+ logger : Logger = new RecordingLogger ( ) ,
10201074) : Partial < sarif . Log > {
10211075 sinon . stub ( diffUtils , "readDiffRangesJsonFile" ) . returns ( diffRanges ) ;
1022- return uploadLib . filterAlertsByDiffRange ( new RecordingLogger ( ) , input ) ;
1076+ return uploadLib . filterAlertsByDiffRange ( logger , input ) ;
10231077}
10241078
10251079test . serial (
@@ -1043,3 +1097,139 @@ test.serial(
10431097 t . deepEqual ( actualOutput , expectedOutput ) ;
10441098 } ,
10451099) ;
1100+
1101+ for ( const [ filePath , uri ] of [
1102+ [ "with space/board.js" , "with%20space/board.js" ] ,
1103+ [ "src/[id]/board.js" , "src/%5Bid%5D/board.js" ] ,
1104+ [ "src/file#1.js" , "src/file%231.js" ] ,
1105+ [ "src/100%.js" , "src/100%25.js" ] ,
1106+ [ "src/literal%20.js" , "src/literal%2520.js" ] ,
1107+ [ "src/foo:bar.js" , "src/foo%3Abar.js" ] ,
1108+ [ "src/caf\u00e9.js" , "src/caf%C3%A9.js" ] ,
1109+ [ "src/caf\u00e9.js" , "src/caf%c3%a9.js" ] ,
1110+ ] ) {
1111+ test . serial (
1112+ `filterAlertsByDiffRange matches percent-encoded URI ${ uri } ` ,
1113+ ( t ) => {
1114+ const matchingResult = createMockResultWithUri ( uri ) ;
1115+ const nonMatchingResult = createMockResultWithUri ( "other.js" ) ;
1116+ const input = createMockSarifWithResults ( [
1117+ matchingResult ,
1118+ nonMatchingResult ,
1119+ ] ) ;
1120+
1121+ const actualOutput = runFilterAlertsByDiffRange ( input , [
1122+ { path : filePath , startLine : 1 , endLine : 3 } ,
1123+ ] ) ;
1124+
1125+ t . deepEqual ( actualOutput . runs ?. [ 0 ] . results , [ matchingResult ] ) ;
1126+ } ,
1127+ ) ;
1128+ }
1129+
1130+ test . serial (
1131+ "filterAlertsByDiffRange filters out percent-encoded URI when outside diff line range" ,
1132+ ( t ) => {
1133+ const outOfRangeResult = createMockResultWithUri (
1134+ "with%20space/board.js" ,
1135+ 2 ,
1136+ ) ;
1137+ const inRangeResult = createMockResultWithUri ( "with%20space/board.js" , 15 ) ;
1138+ const input = createMockSarifWithResults ( [ outOfRangeResult , inRangeResult ] ) ;
1139+ const actualOutput = runFilterAlertsByDiffRange ( input , [
1140+ { path : "with space/board.js" , startLine : 10 , endLine : 20 } ,
1141+ ] ) ;
1142+
1143+ t . deepEqual ( actualOutput . runs ?. [ 0 ] . results , [ inRangeResult ] ) ;
1144+ } ,
1145+ ) ;
1146+
1147+ test . serial (
1148+ "filterAlertsByDiffRange filters out percent-encoded URI when path does not match" ,
1149+ ( t ) => {
1150+ const input = createMockSarifWithResults ( [
1151+ createMockResultWithUri ( "with%20space/board.js" ) ,
1152+ ] ) ;
1153+ const actualOutput = runFilterAlertsByDiffRange ( input , [
1154+ { path : "other/board.js" , startLine : 1 , endLine : 3 } ,
1155+ ] ) ;
1156+
1157+ t . deepEqual ( actualOutput . runs ?. [ 0 ] . results , [ ] ) ;
1158+ } ,
1159+ ) ;
1160+
1161+ test . serial (
1162+ "filterAlertsByDiffRange keeps alert when relatedLocations has a matching percent-encoded URI" ,
1163+ ( t ) => {
1164+ const matchingRelatedResult = createMockResultWithUri (
1165+ "src/promiseUtils.js" ,
1166+ 2 ,
1167+ "with%20space/ParseObject.js" ,
1168+ ) ;
1169+ const nonMatchingResult = createMockResultWithUri ( "other.js" ) ;
1170+ const input = createMockSarifWithResults ( [
1171+ matchingRelatedResult ,
1172+ nonMatchingResult ,
1173+ ] ) ;
1174+
1175+ const actualOutput = runFilterAlertsByDiffRange ( input , [
1176+ { path : "with space/ParseObject.js" , startLine : 1 , endLine : 3 } ,
1177+ ] ) ;
1178+
1179+ t . deepEqual ( actualOutput . runs ?. [ 0 ] . results , [ matchingRelatedResult ] ) ;
1180+ } ,
1181+ ) ;
1182+
1183+ for ( const uri of [ "dir%ZZ/board.js" , "src/bad%.js" , "src/bad%C3%28.js" ] ) {
1184+ test . serial (
1185+ `filterAlertsByDiffRange falls back to raw path for malformed URI ${ uri } ` ,
1186+ ( t ) => {
1187+ const logger = new RecordingLogger ( ) ;
1188+ const matchingResult = createMockResultWithUri ( uri ) ;
1189+ const input = createMockSarifWithResults ( [ matchingResult ] ) ;
1190+ const actualOutput = runFilterAlertsByDiffRange (
1191+ input ,
1192+ [ { path : uri , startLine : 1 , endLine : 3 } ] ,
1193+ logger ,
1194+ ) ;
1195+
1196+ t . deepEqual ( actualOutput . runs ?. [ 0 ] . results , [ matchingResult ] ) ;
1197+ checkExpectedLogMessages ( t , logger . messages , [
1198+ `Failed to decode location URI "${ uri } ", comparing it as a raw path` ,
1199+ ] ) ;
1200+ } ,
1201+ ) ;
1202+ }
1203+
1204+ test . serial (
1205+ "filterAlertsByDiffRange filters out malformed URI when raw path does not match" ,
1206+ ( t ) => {
1207+ const logger = new RecordingLogger ( ) ;
1208+ const input = createMockSarifWithResults ( [
1209+ createMockResultWithUri ( "dir%ZZ/board.js" ) ,
1210+ ] ) ;
1211+ const actualOutput = runFilterAlertsByDiffRange (
1212+ input ,
1213+ [ { path : "src/different.js" , startLine : 1 , endLine : 3 } ] ,
1214+ logger ,
1215+ ) ;
1216+
1217+ t . deepEqual ( actualOutput . runs ?. [ 0 ] . results , [ ] ) ;
1218+ checkExpectedLogMessages ( t , logger . messages , [
1219+ 'Failed to decode location URI "dir%ZZ/board.js", comparing it as a raw path' ,
1220+ ] ) ;
1221+ } ,
1222+ ) ;
1223+
1224+ test . serial (
1225+ "filterAlertsByDiffRange matches raw unencoded path containing valid percent-encoding sequence" ,
1226+ ( t ) => {
1227+ const matchingResult = createMockResultWithUri ( "dir/100%20done.js" ) ;
1228+ const input = createMockSarifWithResults ( [ matchingResult ] ) ;
1229+ const actualOutput = runFilterAlertsByDiffRange ( input , [
1230+ { path : "dir/100%20done.js" , startLine : 1 , endLine : 3 } ,
1231+ ] ) ;
1232+
1233+ t . deepEqual ( actualOutput . runs ?. [ 0 ] . results , [ matchingResult ] ) ;
1234+ } ,
1235+ ) ;
0 commit comments