🤖 Merge PR #65764 k6 v0.45.0 updates by @mstoykov

* Add metadata JS API and maintainance around it

* k6: Add k6/experimental/grpc annotations

* k6: bump k6 to v0.45

* Add browser options

---------

Co-authored-by: Oleg Bespalov <oleg.bespalov@grafana.com>
This commit is contained in:
Mihail Stoykov
2023-06-19 14:59:25 +03:00
committed by GitHub
parent 2928e1eb00
commit 94d68a3fea
8 changed files with 280 additions and 2 deletions

View File

@@ -101,9 +101,20 @@ declare namespace execution {
idInTest: number;
/**
* Hash to set or get VU tags.
* Map to set or get VU tags.
* @deprecated should use `metrics.tags` instead of just `tags`
*/
tags: Record<string, number | string | boolean>;
metrics: {
/**
* Map to set or get VU tags.
*/
tags: Record<string, number | string | boolean>;
/**
* Map to set or get VU metadata.
*/
metadata: Record<string, number | string | boolean>;
}
};
}

154
types/k6/experimental/grpc.d.ts vendored Normal file
View File

@@ -0,0 +1,154 @@
// === Response ===
// ----------------
/**
* gRPC response.
*/
export interface Response {
status: number;
message: object;
headers: object;
trailers: object;
error: object;
}
export interface ConnectParams {
plaintext?: boolean;
reflect?: boolean;
timeout?: string | number;
maxReceiveSize?: number;
maxSendSize?: number;
}
export interface Params {
/**
* @deprecated Use metadata instead.
*/
headers?: object;
metadata?: object;
tags?: object;
timeout?: string | number;
}
export interface GrpcError {
code: number;
details: string[] | object[];
message: string;
}
/**
* This module provides classes for Remote Procedure Calls over HTTP/2.
* https://k6.io/docs/javascript-api/k6-experimental/grpc/
*/
declare namespace grpc {
/**
* gRPC client to interact with a gRPC server.
* https://k6.io/docs/javascript-api/k6-experimental/grpc/client/
*/
class Client {
protected __brand: never;
constructor();
/** Opens a connection to a gRPC server. */
connect(address: string, params?: ConnectParams): void;
/** Loads and parses the protocol buffer descriptors. */
load(importPaths: string[], ...protoFiles: string[]): void;
/** Loads a protoset and parses the protocol buffer descriptors */
loadProtoset(protosetPath: string): void;
/** Invokes an unary RPC request. */
invoke(url: string, request: object, params?: Params): Response;
/** Close the connection. */
close(): void;
}
/**
* StreamEvent describes the possible events that can be emitted
* by a gRPC stream.
*/
enum StreamEvent {
/**
* Event fired when data has been received from the server.
*/
Data = 'data',
/**
* Event fired when a stream has been closed due to an error.
*/
Error = 'error',
/**
* Event fired when the stream closes.
*/
End = 'end',
}
/**
* Stream allows you to use streaming RPCs.
*/
class Stream {
/**
* The gRPC stream constructor, representing a single gRPC stream.
*
* @param client - the gRPC client to use, it must be connected.
* @param url - the RPC method to call.
* @param params - the parameters to use for the RPC call.
*/
constructor(client: Client, url: string, params?: Params);
/**
* Set up handler functions for various events on the gRPC stream.
*
* @param event - the event to listen for
* @param listener - the callback to invoke when the event is emitted
*/
on(event: StreamEvent, listener: (data: object | GrpcError | undefined) => void): void;
/**
* Writes a request to the stream.
*
* @param request - the request (message) to send to the server
*/
write(request: object): void;
/**
* Signals to the server that the client has finished sending messages.
*/
end(): void;
}
const StatusOK: number;
const StatusCanceled: number;
const StatusUnknown: number;
const StatusInvalidArgument: number;
const StatusDeadlineExceeded: number;
const StatusNotFound: number;
const StatusAlreadyExists: number;
const StatusPermissionDenied: number;
const StatusResourceExhausted: number;
const StatusFailedPrecondition: number;
const StatusAborted: number;
const StatusOutOfRange: number;
const StatusUnimplemented: number;
const StatusInternal: number;
const StatusUnavailable: number;
const StatusDataLoss: number;
const StatusUnauthenticated: number;
}
export default grpc;

3
types/k6/index.d.ts vendored
View File

@@ -1,4 +1,4 @@
// Type definitions for k6 0.44
// Type definitions for k6 0.45
// Project: https://k6.io/docs/
// Definitions by: na-- <https://github.com/na-->
// Mihail Stoykov <https://github.com/MStoykov>
@@ -48,6 +48,7 @@ import './experimental/timers';
import './experimental/tracing';
import './experimental/webcrypto';
import './experimental/websockets';
import './experimental/grpc';
import './ws';
import './net/grpc';

View File

@@ -242,6 +242,9 @@ export abstract class BaseScenario {
/** Tags specific to this scenario. */
tags?: { [name: string]: string };
/** Additional options for each scenario */
options?: ScenarioOptions;
}
/**
@@ -439,3 +442,8 @@ export type Scenario =
| ConstantArrivalRateScenario
| RampingArrivalRateScenario
| ExternallyControlledScenario;
export interface ScenarioOptions {
/** Browser specific options */
browser?: any;
}

View File

@@ -23,6 +23,18 @@ execution.vu.tags['mytag3'] = true;
// @ts-expect-error
execution.vu.tags['mytag4'] = [1, 2, 3];
execution.vu.metrics.tags['mytag'] = 'value1';
execution.vu.metrics.tags['mytag2'] = 2;
execution.vu.metrics.tags['mytag3'] = true;
// @ts-expect-error
execution.vu.metrics.tags['mytag4'] = [1, 2, 3];
execution.vu.metrics.metadata['mytag'] = 'value1';
execution.vu.metrics.metadata['mytag2'] = 2;
execution.vu.metrics.metadata['mytag3'] = true;
// @ts-expect-error
execution.vu.metrics.metadata['mytag4'] = [1, 2, 3];
execution.test.abort(); // $ExpectType void
execution.test.abort('this is the reason'); // $ExpectType void
// @ts-expect-error

View File

@@ -0,0 +1,66 @@
import grpc from 'k6/experimental/grpc';
const client = new grpc.Client();
client.connect('hola');
client.connect('localhost:8080', { plaintext: true });
client.connect('localhost:8080', { plaintext: true, reflect: true });
client.connect('localhost:8080', { timeout: 30 });
client.connect('localhost:8080', { timeout: '30' });
client.connect('localhost:8080', { maxReceiveSize: 30, maxSendSize: 30 });
client.close();
client.load(['../googleapis/google'], 'language_service.proto', 'extra_service.proto');
client.loadProtoset('./lib/test.protoset');
const req = {
latitude: 410248224,
longitude: -747127767,
};
const params = {
metadata: { 'x-my-header': 'k6test' },
tags: { k6test: 'yes' },
timeout: 30,
};
const response = client.invoke('main.RouteGuide/GetFeature', req, params);
response.error;
response.headers;
response.message; // $ExpectType object
response.status;
response.trailers;
const params_with_string_timeout = {
metadata: { 'x-my-header': 'k6test' },
tags: { k6test: 'yes' },
timeout: '30',
};
client.invoke('main.RouteGuide/UpdateFeature', req, params_with_string_timeout);
const stream = new grpc.Stream(client, 'main.RouteGuide/GetFeature', params);
stream.on(grpc.StreamEvent.Data, (data) => {
data; // $ExpectType object | GrpcError | undefined
});
stream.write({ latitude: 410248224, longitude: -747127767 });
stream.end();
grpc.StatusOK;
grpc.StatusCanceled;
grpc.StatusUnknown;
grpc.StatusInvalidArgument;
grpc.StatusDeadlineExceeded;
grpc.StatusNotFound;
grpc.StatusAlreadyExists;
grpc.StatusPermissionDenied;
grpc.StatusResourceExhausted;
grpc.StatusFailedPrecondition;
grpc.StatusAborted;
grpc.StatusOutOfRange;
grpc.StatusUnimplemented;
grpc.StatusInternal;
grpc.StatusUnavailable;
grpc.StatusDataLoss;
grpc.StatusUnauthenticated;

View File

@@ -101,3 +101,28 @@ const tlsOptions4: Options = {
},
],
};
const browserScenarios: Scenario[] = [
{
executor: 'shared-iterations',
iterations: 100,
options: {
browser: {
type: 'chromium',
},
},
},
];
const browserScenariosBad: Scenario[] = [
{
executor: 'shared-iterations',
iterations: 100,
options: {
// @ts-expect-error
somethingElse: {
type: 'chromium',
},
},
},
];

View File

@@ -37,6 +37,7 @@
"test/tracing.ts",
"test/webcrypto.ts",
"test/websockets.ts",
"test/experimental/grpc.ts",
"test/ws.ts"
]
}