Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

resources op #1119

Merged
merged 15 commits into from
Oct 30, 2018
1 change: 1 addition & 0 deletions BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ ts_sources = [
"js/read_link.ts",
"js/remove.ts",
"js/rename.ts",
"js/resources.ts",
"js/stat.ts",
"js/symlink.ts",
"js/text_encoding.ts",
Expand Down
1 change: 1 addition & 0 deletions js/deno.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export { truncateSync, truncate } from "./truncate";
export { FileInfo } from "./file_info";
export { connect, dial, listen, Listener, Conn } from "./net";
export { metrics } from "./metrics";
export { resources } from "./resources";
export const args: string[] = [];

// Provide the compiler API in an obfuscated way
Expand Down
25 changes: 25 additions & 0 deletions js/resources.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
import * as msg from "gen/msg_generated";
import * as flatbuffers from "./flatbuffers";
import { assert } from "./util";
import * as dispatch from "./dispatch";

export function resources(): { [key: number]: string } {
const builder = flatbuffers.createBuilder();
msg.Resources.startResources(builder);
const inner = msg.Resource.endResource(builder);
const baseRes = dispatch.sendSync(builder, msg.Any.Resources, inner);
assert(baseRes !== null);
assert(msg.Any.ResourcesRes === baseRes!.innerType());
const res = new msg.ResourcesRes();
assert(baseRes!.inner(res) !== null);

const resources: { [key: number]: string } = {};

for (let i = 0; i < res.resourcesLength(); i++) {
const item = res.resources(i)!;
resources[item.rid()!] = item.repr()!;
}

return resources;
}
bartlomieju marked this conversation as resolved.
Show resolved Hide resolved
48 changes: 48 additions & 0 deletions js/resources_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
import { test, testPerm, assert, assertEqual } from "./test_util.ts";
import * as deno from "deno";

test(function resourcesStdio() {
const res = deno.resources();

assertEqual(res[0], "stdin");
assertEqual(res[1], "stdout");
assertEqual(res[2], "stderr");
});

testPerm({ net: true }, async function resourcesNet() {
const addr = "127.0.0.1:4501";
const listener = deno.listen("tcp", addr);

listener.accept().then(async conn => {
bartlomieju marked this conversation as resolved.
Show resolved Hide resolved
const res = deno.resources();
// besides 3 stdio resources, we should have additional 3 from listen(), accept() and dial()
assertEqual(Object.keys(res).length, 6);
assertEqual(Object.values(res).filter(r => r === "tcpListener").length, 1);
assertEqual(Object.values(res).filter(r => r === "tcpStream").length, 2);

conn.close();
listener.close();
});

const conn = await deno.dial("tcp", addr);
const buf = new Uint8Array(1024);
await conn.read(buf);
conn.close();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's possible that the callback doesn't get called at all. Please add a counter which gets incremented in the callback, and check here
assertEqual(counter, 1)

Also you can remove await conn.read(buf); - I think that has no effect here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You were right about that, I reworked it to use await, let me know if it looks good.

});

test(async function resourcesFile() {
const resourcesBefore = deno.resources();
await deno.open("tests/hello.txt");
const resourcesAfter = deno.resources();

// check that exactly one new resource (file) was added
assertEqual(
Object.keys(resourcesAfter).length,
Object.keys(resourcesBefore).length + 1
);
const newRid = Object.keys(resourcesAfter).find(rid => {
return !resourcesBefore.hasOwnProperty(rid);
});
assertEqual(resourcesAfter[newRid], "fsFile");
});
1 change: 1 addition & 0 deletions js/unit_tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import "./read_dir_test.ts";
import "./read_file_test.ts";
import "./read_link_test.ts";
import "./rename_test.ts";
import "./resources_test.ts";
import "./stat_test.ts";
import "./symlink_test.ts";
import "./text_encoding_test.ts";
Expand Down
13 changes: 13 additions & 0 deletions src/msg.fbs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ union Any {
Rename,
Readlink,
ReadlinkRes,
Resources,
ResourcesRes,
Symlink,
Stat,
StatRes,
Expand Down Expand Up @@ -270,6 +272,17 @@ table ReadlinkRes {
path: string;
}

table Resources {}

table Resource {
rid: int;
repr: string;
}

table ResourcesRes {
resources: [Resource];
}

table Symlink {
oldname: string;
newname: string;
Expand Down
48 changes: 48 additions & 0 deletions src/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use futures::Poll;
use hyper;
use hyper::rt::{Future, Stream};
use remove_dir_all::remove_dir_all;
use resources::get_resource_table_entries;
use std;
use std::fs;
use std::net::{Shutdown, SocketAddr};
Expand Down Expand Up @@ -94,6 +95,7 @@ pub fn dispatch(
msg::Any::Read => op_read,
msg::Any::Remove => op_remove,
msg::Any::Rename => op_rename,
msg::Any::Resources => op_resources,
msg::Any::SetEnv => op_set_env,
msg::Any::Shutdown => op_shutdown,
msg::Any::Start => op_start,
Expand Down Expand Up @@ -1288,3 +1290,49 @@ fn op_metrics(
},
))
}

fn op_resources(
_state: Arc<IsolateState>,
base: &msg::Base,
data: &'static mut [u8],
) -> Box<Op> {
assert_eq!(data.len(), 0);
let cmd_id = base.cmd_id();

let builder = &mut FlatBufferBuilder::new();
let serialized_resources = get_resource_table_entries();

let res: Vec<_> = serialized_resources
.iter()
.map(|(key, value)| {
let repr = builder.create_string(value);

msg::Resource::create(
builder,
&msg::ResourceArgs {
rid: key.clone(),
repr: Some(repr),
..Default::default()
},
)
}).collect();

let resources = builder.create_vector(&res);
let inner = msg::ResourcesRes::create(
builder,
&msg::ResourcesResArgs {
resources: Some(resources),
..Default::default()
},
);

ok_future(serialize_response(
cmd_id,
builder,
msg::BaseArgs {
inner: Some(inner.as_union_value()),
inner_type: msg::Any::ResourcesRes,
..Default::default()
},
))
bartlomieju marked this conversation as resolved.
Show resolved Hide resolved
}
30 changes: 30 additions & 0 deletions src/resources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,36 @@ enum Repr {
TcpStream(tokio::net::TcpStream),
}

pub fn get_resource_table_entries() -> Vec<(i32, String)> {
bartlomieju marked this conversation as resolved.
Show resolved Hide resolved
let table = RESOURCE_TABLE.lock().unwrap();

let tuples = table
.iter()
.map(|(key, value)| (key.clone(), inspect_repr(&value)))
.collect();

tuples
}
ry marked this conversation as resolved.
Show resolved Hide resolved

#[test]
fn test_get_resource_table_entries() {
assert_eq!(get_resource_table_entries().len(), 3);
// TODO: add asserts for add_fs_file, add_tcp_listener, add_tcp_stream
bartlomieju marked this conversation as resolved.
Show resolved Hide resolved
}

fn inspect_repr(repr: &Repr) -> String {
let h_repr = match repr {
Repr::Stdin(_) => "stdin",
Repr::Stdout(_) => "stdout",
Repr::Stderr(_) => "stderr",
Repr::FsFile(_) => "fsFile",
Repr::TcpListener(_) => "tcpListener",
Repr::TcpStream(_) => "tcpStream",
};

String::from(h_repr)
}

// Abstract async file interface.
// Ideally in unix, if Resource represents an OS rid, it will be the same.
#[derive(Debug)]
Expand Down
1 change: 1 addition & 0 deletions tests/hello.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello world!