diff --git a/AUTHORS b/AUTHORS index d0beefff9c..38de58b7cc 100644 --- a/AUTHORS +++ b/AUTHORS @@ -300,3 +300,4 @@ Aaron Jacobs Mustansir Golawala fukayatsu Domenic Denicola +Bryan Cantrill diff --git a/ChangeLog b/ChangeLog index f1aaa7d10f..1d4f8667d1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -255,6 +255,52 @@ * Bug fixes +2012.04.09 Version 0.6.15 (stable) + +* Update npm to 1.1.16 + +* Show licenses in binary installers. + +* unix: add uv_fs_read64, uv_fs_write64 and uv_fs_ftruncate64 (Ben Noordhuis) + +* add 64bit offset fs functions (Igor Zinkovsky) + +* windows: don't report ENOTSOCK when attempting to bind an udp handle twice (Bert Belder) + +* windows: backport pipe-connect-to-file fixes from master (Bert Belder) + +* windows: never call fs event callbacks after closing the watcher (Bert Belder) + +* fs.readFile: don't make the callback before the fd is closed (Bert Belder) + +* windows: use 64bit offsets for uv_fs apis (Igor Zinkovsky) + +* Fix #2061: segmentation fault on OS X due to stat size mismatch (Ben Noordhuis) + + +2012.03.22 Version 0.6.14 (stable), e513ffef7549a56a5af728e1f0c2c0c8f290518a + +* net: don't crash when queued write fails (Igor Zinkovsky) + +* sunos: fix EMFILE on process.memoryUsage() (Bryan Cantrill) + +* crypto: fix compile-time error with openssl 0.9.7e (Ben Noordhuis) + +* unix: ignore ECONNABORTED errors from accept() (Ben Noordhuis) + +* Add UV_ENOSPC and mappings to it (Bert Belder) + +* http-parser: Fix response body is not read (koichik) + +* Upgrade npm to 1.1.12 + - upgrade node-gyp to 0.3.7 + - work around AV-locked directories on Windows + - Fix isaacs/npm#2293 Don't try to 'uninstall' / + - Exclude symbolic links from packages. + - Fix isaacs/npm#2275 Spurious 'unresolvable cycle' error. + - Exclude/include dot files as if they were normal files + + 2012.03.15 Version 0.6.13 (stable), 9f7f86b534f8556290eb8cad915984ff4ca54996 * Windows: Many libuv test fixes (Bert Belder) diff --git a/LICENSE b/LICENSE index 3f7393c44c..a6bc8813ea 100644 --- a/LICENSE +++ b/LICENSE @@ -361,13 +361,6 @@ maintained libraries. The externally maintained libraries used by Node are: # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - # Here are some issues that I've had people identify in my code during reviews, - # that I think are possible to flag automatically in a lint tool. If these were - # caught by lint, it would save time both for myself and that of my reviewers. - # Most likely, some of these are beyond the scope of the current lint framework, - # but I think it is valuable to retain these wish-list items even if they cannot - # be immediately implemented. """ - lib/buffer_ieee754.js. Its license follows: diff --git a/Makefile b/Makefile index 56cb631b05..c6e2e09a24 100644 --- a/Makefile +++ b/Makefile @@ -150,6 +150,13 @@ blog.html: email.md website-upload: doc rsync -r out/doc/ node@nodejs.org:~/web/nodejs.org/ + ssh node@nodejs.org '\ + rm -f ~/web/nodejs.org/dist/latest &&\ + ln -s $(VERSION) ~/web/nodejs.org/dist/latest &&\ + rm -f ~/web/nodejs.org/docs/latest &&\ + ln -s $(VERSION) ~/web/nodejs.org/docs/latest &&\ + rm -f ~/web/nodejs.org/dist/node-latest.tar.gz &&\ + ln -s $(VERSION)/node-$(VERSION).tar.gz ~/web/nodejs.org/dist/node-latest.tar.gz' docopen: out/doc/api/all.html -google-chrome out/doc/api/all.html diff --git a/deps/http_parser/test.c b/deps/http_parser/test.c index db4fc32e39..6af0e787e9 100644 --- a/deps/http_parser/test.c +++ b/deps/http_parser/test.c @@ -44,13 +44,9 @@ struct message { enum http_parser_type type; enum http_method method; int status_code; - char request_path[MAX_ELEMENT_SIZE]; char request_url[MAX_ELEMENT_SIZE]; - char fragment[MAX_ELEMENT_SIZE]; - char query_string[MAX_ELEMENT_SIZE]; char body[MAX_ELEMENT_SIZE]; size_t body_size; - uint16_t port; int num_headers; enum { NONE=0, FIELD, VALUE } last_header_element; char headers [MAX_HEADERS][2][MAX_ELEMENT_SIZE]; @@ -71,7 +67,6 @@ static int currently_parsing_eof; static struct message messages[5]; static int num_messages; -static http_parser_settings *current_pause_parser; /* * R E Q U E S T S * */ const struct message requests[] = @@ -88,9 +83,6 @@ const struct message requests[] = ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/test" ,.request_url= "/test" ,.num_headers= 3 ,.headers= @@ -119,9 +111,6 @@ const struct message requests[] = ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/favicon.ico" ,.request_url= "/favicon.ico" ,.num_headers= 8 ,.headers= @@ -148,9 +137,6 @@ const struct message requests[] = ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/dumbfuck" ,.request_url= "/dumbfuck" ,.num_headers= 1 ,.headers= @@ -169,9 +155,6 @@ const struct message requests[] = ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET - ,.query_string= "page=1" - ,.fragment= "posts-17408" - ,.request_path= "/forums/1/topics/2375" /* XXX request url does include fragment? */ ,.request_url= "/forums/1/topics/2375?page=1#posts-17408" ,.num_headers= 0 @@ -188,9 +171,6 @@ const struct message requests[] = ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/get_no_headers_no_body/world" ,.request_url= "/get_no_headers_no_body/world" ,.num_headers= 0 ,.body= "" @@ -207,9 +187,6 @@ const struct message requests[] = ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/get_one_header_no_body" ,.request_url= "/get_one_header_no_body" ,.num_headers= 1 ,.headers= @@ -230,9 +207,6 @@ const struct message requests[] = ,.http_major= 1 ,.http_minor= 0 ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/get_funky_content_length_body_hello" ,.request_url= "/get_funky_content_length_body_hello" ,.num_headers= 1 ,.headers= @@ -255,9 +229,6 @@ const struct message requests[] = ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_POST - ,.query_string= "q=search" - ,.fragment= "hey" - ,.request_path= "/post_identity_body_world" ,.request_url= "/post_identity_body_world?q=search#hey" ,.num_headers= 3 ,.headers= @@ -282,9 +253,6 @@ const struct message requests[] = ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_POST - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/post_chunked_all_your_base" ,.request_url= "/post_chunked_all_your_base" ,.num_headers= 1 ,.headers= @@ -308,9 +276,6 @@ const struct message requests[] = ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_POST - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/two_chunks_mult_zero_end" ,.request_url= "/two_chunks_mult_zero_end" ,.num_headers= 1 ,.headers= @@ -336,9 +301,6 @@ const struct message requests[] = ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_POST - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/chunked_w_trailing_headers" ,.request_url= "/chunked_w_trailing_headers" ,.num_headers= 3 ,.headers= @@ -364,9 +326,6 @@ const struct message requests[] = ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_POST - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/chunked_w_bullshit_after_length" ,.request_url= "/chunked_w_bullshit_after_length" ,.num_headers= 1 ,.headers= @@ -384,9 +343,6 @@ const struct message requests[] = ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET - ,.query_string= "foo=\"bar\"" - ,.fragment= "" - ,.request_path= "/with_\"stupid\"_quotes" ,.request_url= "/with_\"stupid\"_quotes?foo=\"bar\"" ,.num_headers= 0 ,.headers= { } @@ -410,9 +366,6 @@ const struct message requests[] = ,.http_major= 1 ,.http_minor= 0 ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/test" ,.request_url= "/test" ,.num_headers= 3 ,.headers= { { "Host", "0.0.0.0:5000" } @@ -433,9 +386,6 @@ const struct message requests[] = ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET - ,.query_string= "foo=bar?baz" - ,.fragment= "" - ,.request_path= "/test.cgi" ,.request_url= "/test.cgi?foo=bar?baz" ,.num_headers= 0 ,.headers= {} @@ -454,9 +404,6 @@ const struct message requests[] = ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/test" ,.request_url= "/test" ,.num_headers= 0 ,.headers= { } @@ -481,9 +428,6 @@ const struct message requests[] = ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/demo" ,.request_url= "/demo" ,.num_headers= 7 ,.upgrade="Hot diggity dogg" @@ -512,9 +456,6 @@ const struct message requests[] = ,.http_major= 1 ,.http_minor= 0 ,.method= HTTP_CONNECT - ,.query_string= "" - ,.fragment= "" - ,.request_path= "" ,.request_url= "0-home0.netscape.com:443" ,.num_headers= 2 ,.upgrade="some data\r\nand yet even more data" @@ -534,9 +475,6 @@ const struct message requests[] = ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_REPORT - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/test" ,.request_url= "/test" ,.num_headers= 0 ,.headers= {} @@ -553,9 +491,6 @@ const struct message requests[] = ,.http_major= 0 ,.http_minor= 9 ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/" ,.request_url= "/" ,.num_headers= 0 ,.headers= {} @@ -575,9 +510,6 @@ const struct message requests[] = ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_MSEARCH - ,.query_string= "" - ,.fragment= "" - ,.request_path= "*" ,.request_url= "*" ,.num_headers= 3 ,.headers= { { "HOST", "239.255.255.250:1900" } @@ -587,7 +519,7 @@ const struct message requests[] = ,.body= "" } -#define LINE_FOLDING_IN_HEADER 21 +#define LINE_FOLDING_IN_HEADER 20 , {.name= "line folding in header value" ,.type= HTTP_REQUEST ,.raw= "GET / HTTP/1.1\r\n" @@ -604,9 +536,6 @@ const struct message requests[] = ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/" ,.request_url= "/" ,.num_headers= 2 ,.headers= { { "Line1", "abcdefghijklmno qrs" } @@ -616,7 +545,7 @@ const struct message requests[] = } -#define QUERY_TERMINATED_HOST 22 +#define QUERY_TERMINATED_HOST 21 , {.name= "host terminated by a query string" ,.type= HTTP_REQUEST ,.raw= "GET http://hypnotoad.org?hail=all HTTP/1.1\r\n" @@ -626,16 +555,13 @@ const struct message requests[] = ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET - ,.query_string= "hail=all" - ,.fragment= "" - ,.request_path= "" ,.request_url= "http://hypnotoad.org?hail=all" ,.num_headers= 0 ,.headers= { } ,.body= "" } -#define QUERY_TERMINATED_HOSTPORT 23 +#define QUERY_TERMINATED_HOSTPORT 22 , {.name= "host:port terminated by a query string" ,.type= HTTP_REQUEST ,.raw= "GET http://hypnotoad.org:1234?hail=all HTTP/1.1\r\n" @@ -645,17 +571,13 @@ const struct message requests[] = ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET - ,.query_string= "hail=all" - ,.fragment= "" - ,.request_path= "" ,.request_url= "http://hypnotoad.org:1234?hail=all" - ,.port= 1234 ,.num_headers= 0 ,.headers= { } ,.body= "" } -#define SPACE_TERMINATED_HOSTPORT 24 +#define SPACE_TERMINATED_HOSTPORT 23 , {.name= "host:port terminated by a space" ,.type= HTTP_REQUEST ,.raw= "GET http://hypnotoad.org:1234 HTTP/1.1\r\n" @@ -665,70 +587,14 @@ const struct message requests[] = ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET - ,.query_string= "" - ,.fragment= "" - ,.request_path= "" ,.request_url= "http://hypnotoad.org:1234" - ,.port= 1234 ,.num_headers= 0 ,.headers= { } ,.body= "" } -#define PATCH_REQ 25 -, {.name = "PATCH request" - ,.type= HTTP_REQUEST - ,.raw= "PATCH /file.txt HTTP/1.1\r\n" - "Host: www.example.com\r\n" - "Content-Type: application/example\r\n" - "If-Match: \"e0023aa4e\"\r\n" - "Content-Length: 10\r\n" - "\r\n" - "cccccccccc" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_PATCH - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/file.txt" - ,.request_url= "/file.txt" - ,.num_headers= 4 - ,.headers= { { "Host", "www.example.com" } - , { "Content-Type", "application/example" } - , { "If-Match", "\"e0023aa4e\"" } - , { "Content-Length", "10" } - } - ,.body= "cccccccccc" - } - -#define CONNECT_CAPS_REQUEST 26 -, {.name = "connect caps request" - ,.type= HTTP_REQUEST - ,.raw= "CONNECT HOME0.NETSCAPE.COM:443 HTTP/1.0\r\n" - "User-agent: Mozilla/1.1N\r\n" - "Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n" - "\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 0 - ,.method= HTTP_CONNECT - ,.query_string= "" - ,.fragment= "" - ,.request_path= "" - ,.request_url= "HOME0.NETSCAPE.COM:443" - ,.num_headers= 2 - ,.upgrade="" - ,.headers= { { "User-agent", "Mozilla/1.1N" } - , { "Proxy-authorization", "basic aGVsbG86d29ybGQ=" } - } - ,.body= "" - } - #if !HTTP_PARSER_STRICT -#define UTF8_PATH_REQ 27 +#define UTF8_PATH_REQ 24 , {.name= "utf-8 path request" ,.type= HTTP_REQUEST ,.raw= "GET /δ¶/δt/pope?q=1#narf HTTP/1.1\r\n" @@ -739,9 +605,6 @@ const struct message requests[] = ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET - ,.query_string= "q=1" - ,.fragment= "narf" - ,.request_path= "/δ¶/δt/pope" ,.request_url= "/δ¶/δt/pope?q=1#narf" ,.num_headers= 1 ,.headers= { {"Host", "github.com" } @@ -749,7 +612,7 @@ const struct message requests[] = ,.body= "" } -#define HOSTNAME_UNDERSCORE 28 +#define HOSTNAME_UNDERSCORE 25 , {.name = "hostname underscore" ,.type= HTTP_REQUEST ,.raw= "CONNECT home_0.netscape.com:443 HTTP/1.0\r\n" @@ -761,9 +624,6 @@ const struct message requests[] = ,.http_major= 1 ,.http_minor= 0 ,.method= HTTP_CONNECT - ,.query_string= "" - ,.fragment= "" - ,.request_path= "" ,.request_url= "home_0.netscape.com:443" ,.num_headers= 2 ,.upgrade="" @@ -774,99 +634,49 @@ const struct message requests[] = } #endif /* !HTTP_PARSER_STRICT */ -/* see https://github.com/ry/http-parser/issues/47 */ -#define EAT_TRAILING_CRLF_NO_CONNECTION_CLOSE 29 -, {.name = "eat CRLF between requests, no \"Connection: close\" header" - ,.raw= "POST / HTTP/1.1\r\n" +#define PATCH_REQ 26 +, {.name = "PATCH request" + ,.type= HTTP_REQUEST + ,.raw= "PATCH /file.txt HTTP/1.1\r\n" "Host: www.example.com\r\n" - "Content-Type: application/x-www-form-urlencoded\r\n" - "Content-Length: 4\r\n" + "Content-Type: application/example\r\n" + "If-Match: \"e0023aa4e\"\r\n" + "Content-Length: 10\r\n" "\r\n" - "q=42\r\n" /* note the trailing CRLF */ + "cccccccccc" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 - ,.method= HTTP_POST - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/" - ,.request_url= "/" - ,.num_headers= 3 - ,.upgrade= 0 - ,.headers= { { "Host", "www.example.com" } - , { "Content-Type", "application/x-www-form-urlencoded" } - , { "Content-Length", "4" } - } - ,.body= "q=42" - } - -/* see https://github.com/ry/http-parser/issues/47 */ -#define EAT_TRAILING_CRLF_WITH_CONNECTION_CLOSE 30 -, {.name = "eat CRLF between requests even if \"Connection: close\" is set" - ,.raw= "POST / HTTP/1.1\r\n" - "Host: www.example.com\r\n" - "Content-Type: application/x-www-form-urlencoded\r\n" - "Content-Length: 4\r\n" - "Connection: close\r\n" - "\r\n" - "q=42\r\n" /* note the trailing CRLF */ - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE /* input buffer isn't empty when on_message_complete is called */ - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_POST - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/" - ,.request_url= "/" + ,.method= HTTP_PATCH + ,.request_url= "/file.txt" ,.num_headers= 4 - ,.upgrade= 0 ,.headers= { { "Host", "www.example.com" } - , { "Content-Type", "application/x-www-form-urlencoded" } - , { "Content-Length", "4" } - , { "Connection", "close" } + , { "Content-Type", "application/example" } + , { "If-Match", "\"e0023aa4e\"" } + , { "Content-Length", "10" } } - ,.body= "q=42" - } - -#define PURGE_REQ 31 -, {.name = "PURGE request" - ,.type= HTTP_REQUEST - ,.raw= "PURGE /file.txt HTTP/1.1\r\n" - "Host: www.example.com\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_PURGE - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/file.txt" - ,.request_url= "/file.txt" - ,.num_headers= 1 - ,.headers= { { "Host", "www.example.com" } } - ,.body= "" + ,.body= "cccccccccc" } -#define SEARCH_REQ 32 -, {.name = "SEARCH request" +#define CONNECT_CAPS_REQUEST 27 +, {.name = "connect caps request" ,.type= HTTP_REQUEST - ,.raw= "SEARCH / HTTP/1.1\r\n" - "Host: www.example.com\r\n" + ,.raw= "CONNECT HOME0.NETSCAPE.COM:443 HTTP/1.0\r\n" + "User-agent: Mozilla/1.1N\r\n" + "Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n" "\r\n" - ,.should_keep_alive= TRUE + ,.should_keep_alive= FALSE ,.message_complete_on_eof= FALSE ,.http_major= 1 - ,.http_minor= 1 - ,.method= HTTP_SEARCH - ,.query_string= "" - ,.fragment= "" - ,.request_path= "/" - ,.request_url= "/" - ,.num_headers= 1 - ,.headers= { { "Host", "www.example.com" } } + ,.http_minor= 0 + ,.method= HTTP_CONNECT + ,.request_url= "HOME0.NETSCAPE.COM:443" + ,.num_headers= 2 + ,.upgrade="" + ,.headers= { { "User-agent", "Mozilla/1.1N" } + , { "Proxy-authorization", "basic aGVsbG86d29ybGQ=" } + } ,.body= "" } @@ -970,8 +780,8 @@ const struct message responses[] = , {.name= "404 no headers no body" ,.type= HTTP_RESPONSE ,.raw= "HTTP/1.1 404 Not Found\r\n\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= TRUE + ,.should_keep_alive= TRUE + ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 404 @@ -985,8 +795,8 @@ const struct message responses[] = , {.name= "301 no response phrase" ,.type= HTTP_RESPONSE ,.raw= "HTTP/1.1 301\r\n\r\n" - ,.should_keep_alive = FALSE - ,.message_complete_on_eof= TRUE + ,.should_keep_alive = TRUE + ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 301 @@ -1135,7 +945,40 @@ const struct message responses[] = ,.body= "" } -#define RES_FIELD_UNDERSCORE 9 +#define SPACE_IN_FIELD_RES 9 +/* Should handle spaces in header fields */ +, {.name= "field space" + ,.type= HTTP_RESPONSE + ,.raw= "HTTP/1.1 200 OK\r\n" + "Server: Microsoft-IIS/6.0\r\n" + "X-Powered-By: ASP.NET\r\n" + "en-US Content-Type: text/xml\r\n" /* this is the problem */ + "Content-Type: text/xml\r\n" + "Content-Length: 16\r\n" + "Date: Fri, 23 Jul 2010 18:45:38 GMT\r\n" + "Connection: keep-alive\r\n" + "\r\n" + "hello" /* fake body */ + ,.should_keep_alive= TRUE + ,.message_complete_on_eof= FALSE + ,.http_major= 1 + ,.http_minor= 1 + ,.status_code= 200 + ,.num_headers= 7 + ,.headers= + { { "Server", "Microsoft-IIS/6.0" } + , { "X-Powered-By", "ASP.NET" } + , { "en-US Content-Type", "text/xml" } + , { "Content-Type", "text/xml" } + , { "Content-Length", "16" } + , { "Date", "Fri, 23 Jul 2010 18:45:38 GMT" } + , { "Connection", "keep-alive" } + } + ,.body= "hello" + } + + +#define RES_FIELD_UNDERSCORE 10 /* Should handle spaces in header fields */ , {.name= "field underscore" ,.type= HTTP_RESPONSE @@ -1175,7 +1018,7 @@ const struct message responses[] = ,.body= "" } -#define NON_ASCII_IN_STATUS_LINE 10 +#define NON_ASCII_IN_STATUS_LINE 11 /* Should handle non-ASCII in status line */ , {.name= "non-ASCII in status line" ,.type= HTTP_RESPONSE @@ -1198,7 +1041,7 @@ const struct message responses[] = ,.body= "" } -#define HTTP_VERSION_0_9 11 +#define HTTP_VERSION_0_9 12 /* Should handle HTTP/0.9 */ , {.name= "http version 0.9" ,.type= HTTP_RESPONSE @@ -1214,175 +1057,8 @@ const struct message responses[] = {} ,.body= "" } - -#define NO_CONTENT_LENGTH_NO_TRANSFER_ENCODING_RESPONSE 12 -/* The client should wait for the server's EOF. That is, when neither - * content-length nor transfer-encoding is specified, the end of body - * is specified by the EOF. - */ -, {.name= "neither content-length nor transfer-encoding response" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 OK\r\n" - "Content-Type: text/plain\r\n" - "\r\n" - "hello world" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= TRUE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.num_headers= 1 - ,.headers= - { { "Content-Type", "text/plain" } - } - ,.body= "hello world" - } - -#define NO_BODY_HTTP10_KA_200 13 -, {.name= "HTTP/1.0 with keep-alive and EOF-terminated 200 status" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.0 200 OK\r\n" - "Connection: keep-alive\r\n" - "\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= TRUE - ,.http_major= 1 - ,.http_minor= 0 - ,.status_code= 200 - ,.num_headers= 1 - ,.headers= - { { "Connection", "keep-alive" } - } - ,.body_size= 0 - ,.body= "" - } - -#define NO_BODY_HTTP10_KA_204 14 -, {.name= "HTTP/1.0 with keep-alive and a 204 status" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.0 204 No content\r\n" - "Connection: keep-alive\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 0 - ,.status_code= 204 - ,.num_headers= 1 - ,.headers= - { { "Connection", "keep-alive" } - } - ,.body_size= 0 - ,.body= "" - } - -#define NO_BODY_HTTP11_KA_200 15 -, {.name= "HTTP/1.1 with an EOF-terminated 200 status" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 OK\r\n" - "\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= TRUE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.num_headers= 0 - ,.headers={} - ,.body_size= 0 - ,.body= "" - } - -#define NO_BODY_HTTP11_KA_204 16 -, {.name= "HTTP/1.1 with a 204 status" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 204 No content\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 204 - ,.num_headers= 0 - ,.headers={} - ,.body_size= 0 - ,.body= "" - } - -#define NO_BODY_HTTP11_NOKA_204 17 -, {.name= "HTTP/1.1 with a 204 status and keep-alive disabled" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 204 No content\r\n" - "Connection: close\r\n" - "\r\n" - ,.should_keep_alive= FALSE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 204 - ,.num_headers= 1 - ,.headers= - { { "Connection", "close" } - } - ,.body_size= 0 - ,.body= "" - } - -#define NO_BODY_HTTP11_KA_CHUNKED_200 18 -, {.name= "HTTP/1.1 with chunked endocing and a 200 response" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 OK\r\n" - "Transfer-Encoding: chunked\r\n" - "\r\n" - "0\r\n" - "\r\n" - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.num_headers= 1 - ,.headers= - { { "Transfer-Encoding", "chunked" } - } - ,.body_size= 0 - ,.body= "" - } - -#if !HTTP_PARSER_STRICT -#define SPACE_IN_FIELD_RES 19 -/* Should handle spaces in header fields */ -, {.name= "field space" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 OK\r\n" - "Server: Microsoft-IIS/6.0\r\n" - "X-Powered-By: ASP.NET\r\n" - "en-US Content-Type: text/xml\r\n" /* this is the problem */ - "Content-Type: text/xml\r\n" - "Content-Length: 16\r\n" - "Date: Fri, 23 Jul 2010 18:45:38 GMT\r\n" - "Connection: keep-alive\r\n" - "\r\n" - "hello" /* fake body */ - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.num_headers= 7 - ,.headers= - { { "Server", "Microsoft-IIS/6.0" } - , { "X-Powered-By", "ASP.NET" } - , { "en-US Content-Type", "text/xml" } - , { "Content-Type", "text/xml" } - , { "Content-Length", "16" } - , { "Date", "Fri, 23 Jul 2010 18:45:38 GMT" } - , { "Connection", "keep-alive" } - } - ,.body= "hello" - } -#endif /* !HTTP_PARSER_STRICT */ - , {.name= NULL } /* sentinel */ + }; int @@ -1472,7 +1148,7 @@ message_complete_cb (http_parser *p) "value in both on_message_complete and on_headers_complete " "but it doesn't! ***\n\n"); assert(0); - abort(); + exit(1); } messages[num_messages].message_complete_cb_called = TRUE; @@ -1482,146 +1158,6 @@ message_complete_cb (http_parser *p) return 0; } -/* These dontcall_* callbacks exist so that we can verify that when we're - * paused, no additional callbacks are invoked */ -int -dontcall_message_begin_cb (http_parser *p) -{ - if (p) { } // gcc - fprintf(stderr, "\n\n*** on_message_begin() called on paused parser ***\n\n"); - abort(); -} - -int -dontcall_header_field_cb (http_parser *p, const char *buf, size_t len) -{ - if (p || buf || len) { } // gcc - fprintf(stderr, "\n\n*** on_header_field() called on paused parser ***\n\n"); - abort(); -} - -int -dontcall_header_value_cb (http_parser *p, const char *buf, size_t len) -{ - if (p || buf || len) { } // gcc - fprintf(stderr, "\n\n*** on_header_value() called on paused parser ***\n\n"); - abort(); -} - -int -dontcall_request_url_cb (http_parser *p, const char *buf, size_t len) -{ - if (p || buf || len) { } // gcc - fprintf(stderr, "\n\n*** on_request_url() called on paused parser ***\n\n"); - abort(); -} - -int -dontcall_body_cb (http_parser *p, const char *buf, size_t len) -{ - if (p || buf || len) { } // gcc - fprintf(stderr, "\n\n*** on_body_cb() called on paused parser ***\n\n"); - abort(); -} - -int -dontcall_headers_complete_cb (http_parser *p) -{ - if (p) { } // gcc - fprintf(stderr, "\n\n*** on_headers_complete() called on paused " - "parser ***\n\n"); - abort(); -} - -int -dontcall_message_complete_cb (http_parser *p) -{ - if (p) { } // gcc - fprintf(stderr, "\n\n*** on_message_complete() called on paused " - "parser ***\n\n"); - abort(); -} - -static http_parser_settings settings_dontcall = - {.on_message_begin = dontcall_message_begin_cb - ,.on_header_field = dontcall_header_field_cb - ,.on_header_value = dontcall_header_value_cb - ,.on_url = dontcall_request_url_cb - ,.on_body = dontcall_body_cb - ,.on_headers_complete = dontcall_headers_complete_cb - ,.on_message_complete = dontcall_message_complete_cb - }; - -/* These pause_* callbacks always pause the parser and just invoke the regular - * callback that tracks content. Before returning, we overwrite the parser - * settings to point to the _dontcall variety so that we can verify that - * the pause actually did, you know, pause. */ -int -pause_message_begin_cb (http_parser *p) -{ - http_parser_pause(p, 1); - *current_pause_parser = settings_dontcall; - return message_begin_cb(p); -} - -int -pause_header_field_cb (http_parser *p, const char *buf, size_t len) -{ - http_parser_pause(p, 1); - *current_pause_parser = settings_dontcall; - return header_field_cb(p, buf, len); -} - -int -pause_header_value_cb (http_parser *p, const char *buf, size_t len) -{ - http_parser_pause(p, 1); - *current_pause_parser = settings_dontcall; - return header_value_cb(p, buf, len); -} - -int -pause_request_url_cb (http_parser *p, const char *buf, size_t len) -{ - http_parser_pause(p, 1); - *current_pause_parser = settings_dontcall; - return request_url_cb(p, buf, len); -} - -int -pause_body_cb (http_parser *p, const char *buf, size_t len) -{ - http_parser_pause(p, 1); - *current_pause_parser = settings_dontcall; - return body_cb(p, buf, len); -} - -int -pause_headers_complete_cb (http_parser *p) -{ - http_parser_pause(p, 1); - *current_pause_parser = settings_dontcall; - return headers_complete_cb(p); -} - -int -pause_message_complete_cb (http_parser *p) -{ - http_parser_pause(p, 1); - *current_pause_parser = settings_dontcall; - return message_complete_cb(p); -} - -static http_parser_settings settings_pause = - {.on_message_begin = pause_message_begin_cb - ,.on_header_field = pause_header_field_cb - ,.on_header_value = pause_header_value_cb - ,.on_url = pause_request_url_cb - ,.on_body = pause_body_cb - ,.on_headers_complete = pause_headers_complete_cb - ,.on_message_complete = pause_message_complete_cb - }; - static http_parser_settings settings = {.on_message_begin = message_begin_cb ,.on_header_field = header_field_cb @@ -1691,17 +1227,6 @@ size_t parse_count_body (const char *buf, size_t len) return nparsed; } -size_t parse_pause (const char *buf, size_t len) -{ - size_t nparsed; - http_parser_settings s = settings_pause; - - currently_parsing_eof = (len == 0); - current_pause_parser = &s; - nparsed = http_parser_execute(parser, current_pause_parser, buf, len); - return nparsed; -} - static inline int check_str_eq (const struct message *m, const char *prop, @@ -1742,20 +1267,6 @@ check_num_eq (const struct message *m, #define MESSAGE_CHECK_NUM_EQ(expected, found, prop) \ if (!check_num_eq(expected, #prop, expected->prop, found->prop)) return 0 -#define MESSAGE_CHECK_URL_EQ(u, expected, found, prop, fn) \ -do { \ - char ubuf[256]; \ - \ - if ((u)->field_set & (1 << (fn))) { \ - memcpy(ubuf, (found)->request_url + (u)->field_data[(fn)].off, \ - (u)->field_data[(fn)].len); \ - ubuf[(u)->field_data[(fn)].len] = '\0'; \ - } else { \ - ubuf[0] = '\0'; \ - } \ - \ - check_str_eq(expected, #prop, expected->prop, ubuf); \ -} while(0) int message_eq (int index, const struct message *expected) @@ -1781,28 +1292,6 @@ message_eq (int index, const struct message *expected) MESSAGE_CHECK_STR_EQ(expected, m, request_url); - - /* Check URL components; we can't do this w/ CONNECT since it doesn't - * send us a well-formed URL. - */ - if (*m->request_url && m->method != HTTP_CONNECT) { - struct http_parser_url u; - - if (http_parser_parse_url(m->request_url, strlen(m->request_url), 0, &u)) { - fprintf(stderr, "\n\n*** failed to parse URL %s ***\n\n", - m->request_url); - abort(); - } - - m->port = (u.field_set & (1 << UF_PORT)) ? - u.port : 0; - - MESSAGE_CHECK_URL_EQ(&u, expected, m, query_string, UF_QUERY); - MESSAGE_CHECK_URL_EQ(&u, expected, m, fragment, UF_FRAGMENT); - MESSAGE_CHECK_URL_EQ(&u, expected, m, request_path, UF_PATH); - MESSAGE_CHECK_NUM_EQ(expected, m, port); - } - if (expected->body_size) { MESSAGE_CHECK_NUM_EQ(expected, m, body_size); } else { @@ -1869,7 +1358,7 @@ upgrade_message_fix(char *body, const size_t nread, const size_t nmsgs, ...) { /* Check the portion of the response after its specified upgrade */ if (!check_str_eq(m, "upgrade", body + off, body + nread)) { - abort(); + exit(1); } /* Fix up the response so that message_eq() will verify the beginning @@ -1885,7 +1374,7 @@ upgrade_message_fix(char *body, const size_t nread, const size_t nmsgs, ...) { va_end(ap); printf("\n\n*** Error: expected a message with upgrade ***\n"); - abort(); + exit(1); } static void @@ -1931,218 +1420,6 @@ print_error (const char *raw, size_t error_location) fprintf(stderr, "^\n\nerror location: %u\n", (unsigned int)error_location); } -void -test_preserve_data (void) -{ - char my_data[] = "application-specific data"; - http_parser parser; - parser.data = my_data; - http_parser_init(&parser, HTTP_REQUEST); - if (parser.data != my_data) { - printf("\n*** parser.data not preserved accross http_parser_init ***\n\n"); - abort(); - } -} - -struct url_test { - const char *name; - const char *url; - int is_connect; - struct http_parser_url u; - int rv; -}; - -const struct url_test url_tests[] = -{ {.name="proxy request" - ,.url="http://hostname/" - ,.is_connect=0 - ,.u= - {.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PATH) - ,.port=0 - ,.field_data= - {{ 0, 4 } /* UF_SCHEMA */ - ,{ 7, 8 } /* UF_HOST */ - ,{ 0, 0 } /* UF_PORT */ - ,{ 15, 1 } /* UF_PATH */ - ,{ 0, 0 } /* UF_QUERY */ - ,{ 0, 0 } /* UF_FRAGMENT */ - } - } - ,.rv=0 - } - -, {.name="CONNECT request" - ,.url="hostname:443" - ,.is_connect=1 - ,.u= - {.field_set=(1 << UF_HOST) | (1 << UF_PORT) - ,.port=443 - ,.field_data= - {{ 0, 0 } /* UF_SCHEMA */ - ,{ 0, 8 } /* UF_HOST */ - ,{ 9, 3 } /* UF_PORT */ - ,{ 0, 0 } /* UF_PATH */ - ,{ 0, 0 } /* UF_QUERY */ - ,{ 0, 0 } /* UF_FRAGMENT */ - } - } - ,.rv=0 - } - -, {.name="proxy ipv6 request" - ,.url="http://[1:2::3:4]/" - ,.is_connect=0 - ,.u= - {.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PATH) - ,.port=0 - ,.field_data= - {{ 0, 4 } /* UF_SCHEMA */ - ,{ 8, 8 } /* UF_HOST */ - ,{ 0, 0 } /* UF_PORT */ - ,{ 17, 1 } /* UF_PATH */ - ,{ 0, 0 } /* UF_QUERY */ - ,{ 0, 0 } /* UF_FRAGMENT */ - } - } - ,.rv=0 - } - -, {.name="CONNECT ipv6 address" - ,.url="[1:2::3:4]:443" - ,.is_connect=1 - ,.u= - {.field_set=(1 << UF_HOST) | (1 << UF_PORT) - ,.port=443 - ,.field_data= - {{ 0, 0 } /* UF_SCHEMA */ - ,{ 1, 8 } /* UF_HOST */ - ,{ 11, 3 } /* UF_PORT */ - ,{ 0, 0 } /* UF_PATH */ - ,{ 0, 0 } /* UF_QUERY */ - ,{ 0, 0 } /* UF_FRAGMENT */ - } - } - ,.rv=0 - } - -, {.name="extra ? in query string" - ,.url="http://a.tbcdn.cn/p/fp/2010c/??fp-header-min.css,fp-base-min.css,fp-channel-min.css,fp-product-min.css,fp-mall-min.css,fp-category-min.css,fp-sub-min.css,fp-gdp4p-min.css,fp-css3-min.css,fp-misc-min.css?t=20101022.css" - ,.is_connect=0 - ,.u= - {.field_set=(1<field_set, u->port); - for (i = 0; i < UF_MAX; i++) { - if ((u->field_set & (1 << i)) == 0) { - printf("\tfield_data[%u]: unset\n", i); - continue; - } - - memcpy(part, url + u->field_data[i].off, u->field_data[i].len); - part[u->field_data[i].len] = '\0'; - - printf("\tfield_data[%u]: off: %u len: %u part: \"%s\"\n", - i, - u->field_data[i].off, - u->field_data[i].len, - part); - } -} - -void -test_parse_url (void) -{ - struct http_parser_url u; - const struct url_test *test; - unsigned int i; - int rv; - - for (i = 0; i < (sizeof(url_tests) / sizeof(url_tests[0])); i++) { - test = &url_tests[i]; - memset(&u, 0, sizeof(u)); - - rv = http_parser_parse_url(test->url, - strlen(test->url), - test->is_connect, - &u); - - if (test->rv == 0) { - if (rv != 0) { - printf("\n*** http_parser_parse_url(\"%s\") \"%s\" test failed, " - "unexpected rv %d ***\n\n", test->url, test->name, rv); - abort(); - } - - if (memcmp(&u, &test->u, sizeof(u)) != 0) { - printf("\n*** http_parser_parse_url(\"%s\") \"%s\" failed ***\n", - test->url, test->name); - - printf("target http_parser_url:\n"); - dump_url(test->url, &test->u); - printf("result http_parser_url:\n"); - dump_url(test->url, &u); - - abort(); - } - } else { - /* test->rv != 0 */ - if (rv == 0) { - printf("\n*** http_parser_parse_url(\"%s\") \"%s\" test failed, " - "unexpected rv %d ***\n\n", test->url, test->name, rv); - abort(); - } - } - } -} void test_message (const struct message *message) @@ -2167,7 +1444,7 @@ test_message (const struct message *message) if (read != msg1len) { print_error(msg1, read); - abort(); + exit(1); } } @@ -2181,24 +1458,24 @@ test_message (const struct message *message) if (read != msg2len) { print_error(msg2, read); - abort(); + exit(1); } read = parse(NULL, 0); if (read != 0) { print_error(message->raw, read); - abort(); + exit(1); } test: if (num_messages != 1) { printf("\n*** num_messages != 1 after testing '%s' ***\n\n", message->name); - abort(); + exit(1); } - if(!message_eq(0, message)) abort(); + if(!message_eq(0, message)) exit(1); parser_free(); } @@ -2219,7 +1496,7 @@ test_message_count_body (const struct message *message) read = parse_count_body(message->raw + i, toread); if (read != toread) { print_error(message->raw, read); - abort(); + exit(1); } } @@ -2227,15 +1504,15 @@ test_message_count_body (const struct message *message) read = parse_count_body(NULL, 0); if (read != 0) { print_error(message->raw, read); - abort(); + exit(1); } if (num_messages != 1) { printf("\n*** num_messages != 1 after testing '%s' ***\n\n", message->name); - abort(); + exit(1); } - if(!message_eq(0, message)) abort(); + if(!message_eq(0, message)) exit(1); parser_free(); } @@ -2267,7 +1544,7 @@ test_simple (const char *buf, enum http_errno err_expected) #endif fprintf(stderr, "\n*** test_simple expected %s, but saw %s ***\n\n%s\n", http_errno_name(err_expected), http_errno_name(err), buf); - abort(); + exit(1); } } @@ -2296,54 +1573,7 @@ test_header_overflow_error (int req) } fprintf(stderr, "\n*** Error expected but none in header overflow test ***\n"); - abort(); -} - -static void -test_content_length_overflow (const char *buf, size_t buflen, int expect_ok) -{ - http_parser parser; - http_parser_init(&parser, HTTP_RESPONSE); - http_parser_execute(&parser, &settings_null, buf, buflen); - - if (expect_ok) - assert(HTTP_PARSER_ERRNO(&parser) == HPE_OK); - else - assert(HTTP_PARSER_ERRNO(&parser) == HPE_INVALID_CONTENT_LENGTH); -} - -void -test_header_content_length_overflow_error (void) -{ -#define X(size) \ - "HTTP/1.1 200 OK\r\n" \ - "Content-Length: " #size "\r\n" \ - "\r\n" - const char a[] = X(18446744073709551614); /* 2^64-2 */ - const char b[] = X(18446744073709551615); /* 2^64-1 */ - const char c[] = X(18446744073709551616); /* 2^64 */ -#undef X - test_content_length_overflow(a, sizeof(a) - 1, 1); /* expect ok */ - test_content_length_overflow(b, sizeof(b) - 1, 0); /* expect failure */ - test_content_length_overflow(c, sizeof(c) - 1, 0); /* expect failure */ -} - -void -test_chunk_content_length_overflow_error (void) -{ -#define X(size) \ - "HTTP/1.1 200 OK\r\n" \ - "Transfer-Encoding: chunked\r\n" \ - "\r\n" \ - #size "\r\n" \ - "..." - const char a[] = X(FFFFFFFFFFFFFFFE); /* 2^64-2 */ - const char b[] = X(FFFFFFFFFFFFFFFF); /* 2^64-1 */ - const char c[] = X(10000000000000000); /* 2^64 */ -#undef X - test_content_length_overflow(a, sizeof(a) - 1, 1); /* expect ok */ - test_content_length_overflow(b, sizeof(b) - 1, 0); /* expect failure */ - test_content_length_overflow(c, sizeof(c) - 1, 0); /* expect failure */ + exit(1); } void @@ -2376,7 +1606,7 @@ test_no_overflow_long_body (int req, size_t length) "\n*** error in test_no_overflow_long_body %s of length %zu ***\n", req ? "REQUEST" : "RESPONSE", length); - abort(); + exit(1); } void @@ -2408,26 +1638,26 @@ test_multiple3 (const struct message *r1, const struct message *r2, const struct if (read != strlen(total)) { print_error(total, read); - abort(); + exit(1); } read = parse(NULL, 0); if (read != 0) { print_error(total, read); - abort(); + exit(1); } test: if (message_count != num_messages) { fprintf(stderr, "\n\n*** Parser didn't see 3 messages only %d *** \n", num_messages); - abort(); + exit(1); } - if (!message_eq(0, r1)) abort(); - if (message_count > 1 && !message_eq(1, r2)) abort(); - if (message_count > 2 && !message_eq(2, r3)) abort(); + if (!message_eq(0, r1)) exit(1); + if (message_count > 1 && !message_eq(1, r2)) exit(1); + if (message_count > 2 && !message_eq(2, r3)) exit(1); parser_free(); } @@ -2550,7 +1780,7 @@ test: fprintf(stderr, "buf1 (%u) %s\n\n", (unsigned int)buf1_len, buf1); fprintf(stderr, "buf2 (%u) %s\n\n", (unsigned int)buf2_len , buf2); fprintf(stderr, "buf3 (%u) %s\n", (unsigned int)buf3_len, buf3); - abort(); + exit(1); } // user required to free the result @@ -2584,58 +1814,6 @@ create_large_chunked_message (int body_size_in_kb, const char* headers) return buf; } -/* Verify that we can pause parsing at any of the bytes in the - * message and still get the result that we're expecting. */ -void -test_message_pause (const struct message *msg) -{ - char *buf = (char*) msg->raw; - size_t buflen = strlen(msg->raw); - size_t nread; - - parser_init(msg->type); - - do { - nread = parse_pause(buf, buflen); - - // We can only set the upgrade buffer once we've gotten our message - // completion callback. - if (messages[0].message_complete_cb_called && - msg->upgrade && - parser->upgrade) { - messages[0].upgrade = buf + nread; - goto test; - } - - if (nread < buflen) { - - // Not much do to if we failed a strict-mode check - if (HTTP_PARSER_ERRNO(parser) == HPE_STRICT) { - parser_free(); - return; - } - - assert (HTTP_PARSER_ERRNO(parser) == HPE_PAUSED); - } - - buf += nread; - buflen -= nread; - http_parser_pause(parser, 0); - } while (buflen > 0); - - nread = parse_pause(NULL, 0); - assert (nread == 0); - -test: - if (num_messages != 1) { - printf("\n*** num_messages != 1 after testing '%s' ***\n\n", msg->name); - abort(); - } - - if(!message_eq(0, msg)) abort(); - - parser_free(); -} int main (void) @@ -2650,10 +1828,6 @@ main (void) for (request_count = 0; requests[request_count].name; request_count++); for (response_count = 0; responses[response_count].name; response_count++); - //// API - test_preserve_data(); - test_parse_url(); - //// OVERFLOW CONDITIONS test_header_overflow_error(HTTP_REQUEST); @@ -2664,19 +1838,12 @@ main (void) test_no_overflow_long_body(HTTP_RESPONSE, 1000); test_no_overflow_long_body(HTTP_RESPONSE, 100000); - test_header_content_length_overflow_error(); - test_chunk_content_length_overflow_error(); - //// RESPONSES for (i = 0; i < response_count; i++) { test_message(&responses[i]); } - for (i = 0; i < response_count; i++) { - test_message_pause(&responses[i]); - } - for (i = 0; i < response_count; i++) { if (!responses[i].should_keep_alive) continue; for (j = 0; j < response_count; j++) { @@ -2721,7 +1888,7 @@ main (void) printf("response scan 1/2 "); test_scan( &responses[TRAILING_SPACE_ON_CHUNKED_BODY] - , &responses[NO_BODY_HTTP10_KA_204] + , &responses[NO_HEADERS_NO_BODY_404] , &responses[NO_REASON_PHRASE] ); @@ -2852,9 +2019,7 @@ main (void) test_message(&requests[i]); } - for (i = 0; i < request_count; i++) { - test_message_pause(&requests[i]); - } + for (i = 0; i < request_count; i++) { if (!requests[i].should_keep_alive) continue; diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c index a8fe0abb97..8dc7147310 100644 --- a/deps/uv/test/test-fs.c +++ b/deps/uv/test/test-fs.c @@ -225,7 +225,6 @@ static void close_cb(uv_fs_t* req) { uv_fs_req_cleanup(req); if (close_cb_count == 3) { r = uv_fs_unlink(loop, &unlink_req, "test_file2", unlink_cb); - ASSERT(r == 0); } } @@ -238,7 +237,6 @@ static void ftruncate_cb(uv_fs_t* req) { ftruncate_cb_count++; uv_fs_req_cleanup(req); r = uv_fs_close(loop, &close_req, open_req1.result, close_cb); - ASSERT(r == 0); } @@ -257,7 +255,6 @@ static void read_cb(uv_fs_t* req) { ASSERT(strcmp(buf, "test-bu") == 0); r = uv_fs_close(loop, &close_req, open_req1.result, close_cb); } - ASSERT(r == 0); } @@ -277,7 +274,6 @@ static void open_cb(uv_fs_t* req) { memset(buf, 0, sizeof(buf)); r = uv_fs_read(loop, &read_req, open_req1.result, buf, sizeof(buf), -1, read_cb); - ASSERT(r == 0); } @@ -302,7 +298,6 @@ static void fsync_cb(uv_fs_t* req) { fsync_cb_count++; uv_fs_req_cleanup(req); r = uv_fs_close(loop, &close_req, open_req1.result, close_cb); - ASSERT(r == 0); } @@ -314,7 +309,6 @@ static void fdatasync_cb(uv_fs_t* req) { fdatasync_cb_count++; uv_fs_req_cleanup(req); r = uv_fs_fsync(loop, &fsync_req, open_req1.result, fsync_cb); - ASSERT(r == 0); } @@ -326,7 +320,6 @@ static void write_cb(uv_fs_t* req) { write_cb_count++; uv_fs_req_cleanup(req); r = uv_fs_fdatasync(loop, &fdatasync_req, open_req1.result, fdatasync_cb); - ASSERT(r == 0); } @@ -339,7 +332,6 @@ static void create_cb(uv_fs_t* req) { uv_fs_req_cleanup(req); r = uv_fs_write(loop, &write_req, req->result, test_buf, sizeof(test_buf), -1, write_cb); - ASSERT(r == 0); } @@ -1673,59 +1665,3 @@ TEST_IMPL(fs_rename_to_existing_file) { return 0; } - - -TEST_IMPL(fs_read_file_eof) { - int r; - - /* Setup. */ - unlink("test_file"); - - loop = uv_default_loop(); - - r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT, - S_IWRITE | S_IREAD, NULL); - ASSERT(r != -1); - ASSERT(open_req1.result != -1); - uv_fs_req_cleanup(&open_req1); - - r = uv_fs_write(loop, &write_req, open_req1.result, test_buf, - sizeof(test_buf), -1, NULL); - ASSERT(r != -1); - ASSERT(write_req.result != -1); - uv_fs_req_cleanup(&write_req); - - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); - ASSERT(r != -1); - ASSERT(close_req.result != -1); - uv_fs_req_cleanup(&close_req); - - r = uv_fs_open(loop, &open_req1, "test_file", O_RDONLY, 0, NULL); - ASSERT(r != -1); - ASSERT(open_req1.result != -1); - uv_fs_req_cleanup(&open_req1); - - memset(buf, 0, sizeof(buf)); - r = uv_fs_read(loop, &read_req, open_req1.result, buf, sizeof(buf), -1, - NULL); - ASSERT(r != -1); - ASSERT(read_req.result != -1); - ASSERT(strcmp(buf, test_buf) == 0); - uv_fs_req_cleanup(&read_req); - - r = uv_fs_read(loop, &read_req, open_req1.result, buf, sizeof(buf), - read_req.result, NULL); - ASSERT(r == 0); - ASSERT(read_req.result == 0); - uv_fs_req_cleanup(&read_req); - - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); - ASSERT(r != -1); - ASSERT(close_req.result != -1); - uv_fs_req_cleanup(&close_req); - - /* Cleanup */ - unlink("test_file"); - - return 0; -} diff --git a/doc/community/index.html b/doc/community/index.html index 7087f795f8..13f73230b0 100644 --- a/doc/community/index.html +++ b/doc/community/index.html @@ -134,7 +134,7 @@
nodejs.ir Iran group in Persian
- nodejs.jp Japan user group + nodejs.jp Japan user group
CNodeJS.org Chinese community
@@ -142,7 +142,13 @@
HKNoJ Hong Kong community
- nodejs.tw Taiwan community

+ nodejs.tw Taiwan community +
+ Node Hispano Spanish language community +
+ OctoberSkyJs Korea Node.js community +

+ diff --git a/doc/images/linkedin-logo.png b/doc/images/linkedin-logo.png index 2ad9fb2c0c..1c79cf4acd 100644 Binary files a/doc/images/linkedin-logo.png and b/doc/images/linkedin-logo.png differ diff --git a/doc/images/microsoft-logo.png b/doc/images/microsoft-logo.png index 6dac0f39b6..1a58d10762 100644 Binary files a/doc/images/microsoft-logo.png and b/doc/images/microsoft-logo.png differ diff --git a/doc/images/yahoo-logo.png b/doc/images/yahoo-logo.png index 05d75b3513..689d21b71e 100644 Binary files a/doc/images/yahoo-logo.png and b/doc/images/yahoo-logo.png differ diff --git a/doc/pipe.css b/doc/pipe.css index fa8b44c23d..5c1ce79b0e 100644 --- a/doc/pipe.css +++ b/doc/pipe.css @@ -150,16 +150,7 @@ h1 a, h2 a, h3 a, h4 a font-size: 11px; } -#quotes ul li.ebay { - margin-top: -10px; -} - -#quotes ul li.linkedin { - margin-top: -4px; -} - -#quotes ul li.yahoo { - margin-top: -4px; +#quotes ul li:last-child { padding-right: 0; } diff --git a/lib/fs.js b/lib/fs.js index ca98e2aa65..fc1e1b830b 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -106,6 +106,7 @@ fs.readFile = function(path, encoding_) { var readStream = fs.createReadStream(path); var buffers = []; var nread = 0; + var error; readStream.on('data', function(chunk) { buffers.push(chunk); @@ -113,11 +114,18 @@ fs.readFile = function(path, encoding_) { }); readStream.on('error', function(er) { - callback(er); + error = er; readStream.destroy(); + if (!readStream.fd) { + readStream.emit('close'); + } }); - readStream.on('end', function() { + readStream.on('close', function() { + if (error) { + return callback(error); + } + // copy all the buffers into one var buffer; switch (buffers.length) { diff --git a/lib/net.js b/lib/net.js index 6c2e86e832..8d36c34e60 100644 --- a/lib/net.js +++ b/lib/net.js @@ -114,6 +114,7 @@ function initSocketHandle(self) { self._flags = 0; self._connectQueueSize = 0; self.destroyed = false; + self.errorEmitted = false; self.bytesRead = 0; self.bytesWritten = 0; @@ -278,7 +279,7 @@ Socket.prototype.end = function(data, encoding) { var shutdownReq = this._handle.shutdown(); if (!shutdownReq) { - this.destroy(errnoException(errno, 'shutdown')); + this._destroy(errnoException(errno, 'shutdown')); return false; } @@ -301,7 +302,7 @@ function afterShutdown(status, handle, req) { } if (self._flags & FLAG_GOT_EOF || !self.readable) { - self.destroy(); + self._destroy(); } else { } } @@ -312,7 +313,7 @@ Socket.prototype.destroySoon = function() { this._flags |= FLAG_DESTROY_SOON; if (this._pendingWriteReqs == 0) { - this.destroy(); + this._destroy(); } }; @@ -324,11 +325,24 @@ Socket.prototype._connectQueueCleanUp = function(exception) { }; -Socket.prototype.destroy = function(exception) { - if (this.destroyed) return; - +Socket.prototype._destroy = function(exception, cb) { var self = this; + function fireErrorCallbacks() { + if (cb) cb(exception); + if (exception && !self.errorEmitted) { + process.nextTick(function() { + self.emit('error', exception); + }); + self.errorEmitted = true; + } + }; + + if (this.destroyed) { + fireErrorCallbacks(); + return; + } + self._connectQueueCleanUp(); debug('destroy'); @@ -349,8 +363,9 @@ Socket.prototype.destroy = function(exception) { this._handle = null; } + fireErrorCallbacks(); + process.nextTick(function() { - if (exception) self.emit('error', exception); self.emit('close', exception ? true : false); }); @@ -358,6 +373,11 @@ Socket.prototype.destroy = function(exception) { }; +Socket.prototype.destroy = function(exception) { + this._destroy(exception); +} + + function onread(buffer, offset, length) { var handle = this; var self = handle.socket; @@ -396,7 +416,7 @@ function onread(buffer, offset, length) { // We call destroy() before end(). 'close' not emitted until nextTick so // the 'end' event will come first as required. - if (!self.writable) self.destroy(); + if (!self.writable) self._destroy(); if (!self.allowHalfOpen) self.end(); if (self._events && self._events['end']) self.emit('end'); @@ -404,9 +424,9 @@ function onread(buffer, offset, length) { } else { // Error if (errno == 'ECONNRESET') { - self.destroy(); + self._destroy(); } else { - self.destroy(errnoException(errno, 'read')); + self._destroy(errnoException(errno, 'read')); } } } @@ -484,13 +504,16 @@ Socket.prototype.write = function(data, arg1, arg2) { Socket.prototype._write = function(data, encoding, cb) { timers.active(this); - if (!this._handle) throw new Error('This socket is closed.'); + if (!this._handle) { + this._destroy(new Error('This socket is closed.'), cb); + return false; + } // `encoding` is unused right now, `data` is always a buffer. var writeReq = this._handle.write(data); if (!writeReq) { - this.destroy(errnoException(errno, 'write')); + this._destroy(errnoException(errno, 'write'), cb); return false; } @@ -511,7 +534,7 @@ function afterWrite(status, handle, req, buffer) { } if (status) { - self.destroy(errnoException(errno, 'write')); + self._destroy(errnoException(errno, 'write'), req.cb); return; } @@ -526,7 +549,7 @@ function afterWrite(status, handle, req, buffer) { if (req.cb) req.cb(); if (self._pendingWriteReqs == 0 && self._flags & FLAG_DESTROY_SOON) { - self.destroy(); + self._destroy(); } } @@ -563,7 +586,7 @@ function connect(self, address, port, addressType, localAddress) { if (connectReq !== null) { connectReq.oncomplete = afterConnect; } else { - self.destroy(errnoException(errno, 'connect')); + self._destroy(errnoException(errno, 'connect')); } } @@ -617,7 +640,7 @@ Socket.prototype.connect = function(options, cb) { // error event to the next tick. process.nextTick(function() { self.emit('error', err); - self.destroy(); + self._destroy(); }); } else { timers.active(self); @@ -662,8 +685,9 @@ function afterConnect(status, handle, req, readable, writable) { if (self._connectQueue) { debug('Drain the connect queue'); - for (var i = 0; i < self._connectQueue.length; i++) { - self._write.apply(self, self._connectQueue[i]); + var connectQueue = self._connectQueue; + for (var i = 0; i < connectQueue.length; i++) { + self._write.apply(self, connectQueue[i]); } self._connectQueueCleanUp(); } @@ -677,7 +701,7 @@ function afterConnect(status, handle, req, readable, writable) { } } else { self._connectQueueCleanUp(); - self.destroy(errnoException(errno, 'connect')); + self._destroy(errnoException(errno, 'connect')); } } diff --git a/src/node.h b/src/node.h index f7417c829f..a2cf2eb9bb 100644 --- a/src/node.h +++ b/src/node.h @@ -75,6 +75,14 @@ #define NODE_STRINGIFY_HELPER(n) #n #endif +#ifndef STATIC_ASSERT +#if defined(_MSC_VER) +# define STATIC_ASSERT(expr) static_assert(expr, "") +# else +# define STATIC_ASSERT(expr) static_cast((sizeof(char[-1 + !!(expr)]))) +# endif +#endif + namespace node { int Start(int argc, char *argv[]); diff --git a/src/node_crypto.cc b/src/node_crypto.cc index c05e8e3361..b99d9b074b 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -972,7 +972,10 @@ Handle Connection::New(const Arguments& args) { } -void Connection::SSLInfoCallback(const SSL *ssl, int where, int ret) { +void Connection::SSLInfoCallback(const SSL *ssl_, int where, int ret) { + // Be compatible with older versions of OpenSSL. SSL_get_app_data() wants + // a non-const SSL* in OpenSSL <= 0.9.7e. + SSL* ssl = const_cast(ssl_); if (where & SSL_CB_HANDSHAKE_START) { HandleScope scope; Connection* c = static_cast(SSL_get_app_data(ssl)); diff --git a/src/node_file.cc b/src/node_file.cc index f4b53a1b2f..805dc532f5 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -39,7 +39,6 @@ # include #endif - namespace node { using namespace v8; @@ -70,10 +69,41 @@ static Persistent buf_symbol; static Persistent oncomplete_sym; -#ifdef _LARGEFILE_SOURCE -static inline int IsInt64(double x) { - return x == static_cast(static_cast(x)); -} +#ifndef _LARGEFILE_SOURCE + typedef off_t node_off_t; +# define ASSERT_OFFSET(a) \ + STATIC_ASSERT(sizeof(node_off_t) * CHAR_BIT >= 32); \ + if (!(a)->IsUndefined() && !(a)->IsNull() && !(a)->IsInt32()) { \ + return ThrowException(Exception::TypeError(String::New("Not an integer"))); \ + } +# define ASSERT_TRUNCATE_LENGTH(a) \ + if (!(a)->IsUndefined() && !(a)->IsNull() && !(a)->IsUint32()) { \ + return ThrowException(Exception::TypeError(String::New("Not an integer"))); \ + } +# define GET_OFFSET(a) ((a)->IsNumber() ? (a)->Int32Value() : -1) +# define GET_TRUNCATE_LENGTH(a) ((a)->Uint32Value()) +#else +# ifdef _WIN32 +# define NODE_USE_64BIT_UV_FS_API + typedef int64_t node_off_t; +# else + typedef off_t node_off_t; +# endif +# define ASSERT_OFFSET(a) \ + STATIC_ASSERT(sizeof(node_off_t) * CHAR_BIT >= 64); \ + if (!(a)->IsUndefined() && !(a)->IsNull() && !IsInt64((a)->NumberValue())) { \ + return ThrowException(Exception::TypeError(String::New("Not an integer"))); \ + } +# define ASSERT_TRUNCATE_LENGTH(a) \ + if (!(a)->IsUndefined() && !(a)->IsNull() && !IsInt64((a)->NumberValue())) { \ + return ThrowException(Exception::TypeError(String::New("Not an integer"))); \ + } +# define GET_OFFSET(a) ((a)->IsNumber() ? (a)->IntegerValue() : -1) +# define GET_TRUNCATE_LENGTH(a) ((a)->IntegerValue()) + + static inline int IsInt64(double x) { + return x == static_cast(static_cast(x)); + } #endif @@ -475,20 +505,6 @@ static Handle Rename(const Arguments& args) { } } -#ifndef _LARGEFILE_SOURCE -#define ASSERT_TRUNCATE_LENGTH(a) \ - if (!(a)->IsUndefined() && !(a)->IsNull() && !(a)->IsUint32()) { \ - return ThrowException(Exception::TypeError(String::New("Not an integer"))); \ - } -#define GET_TRUNCATE_LENGTH(a) ((a)->Uint32Value()) -#else -#define ASSERT_TRUNCATE_LENGTH(a) \ - if (!(a)->IsUndefined() && !(a)->IsNull() && !IsInt64((a)->NumberValue())) { \ - return ThrowException(Exception::TypeError(String::New("Not an integer"))); \ - } -#define GET_TRUNCATE_LENGTH(a) ((a)->IntegerValue()) -#endif - static Handle Truncate(const Arguments& args) { HandleScope scope; @@ -499,12 +515,20 @@ static Handle Truncate(const Arguments& args) { int fd = args[0]->Int32Value(); ASSERT_TRUNCATE_LENGTH(args[1]); - off_t len = GET_TRUNCATE_LENGTH(args[1]); + node_off_t len = GET_TRUNCATE_LENGTH(args[1]); if (args[2]->IsFunction()) { +#ifdef NODE_USE_64BIT_UV_FS_API + ASYNC_CALL(ftruncate64, args[2], fd, len) +#else ASYNC_CALL(ftruncate, args[2], fd, len) +#endif } else { +#ifdef NODE_USE_64BIT_UV_FS_API + SYNC_CALL(ftruncate64, 0, fd, len) +#else SYNC_CALL(ftruncate, 0, fd, len) +#endif return Undefined(); } } @@ -674,20 +698,6 @@ static Handle Open(const Arguments& args) { } } -#ifndef _LARGEFILE_SOURCE -#define ASSERT_OFFSET(a) \ - if (!(a)->IsUndefined() && !(a)->IsNull() && !(a)->IsInt32()) { \ - return ThrowException(Exception::TypeError(String::New("Not an integer"))); \ - } -#define GET_OFFSET(a) ((a)->IsNumber() ? (a)->Int32Value() : -1) -#else -#define ASSERT_OFFSET(a) \ - if (!(a)->IsUndefined() && !(a)->IsNull() && !IsInt64((a)->NumberValue())) { \ - return ThrowException(Exception::TypeError(String::New("Not an integer"))); \ - } -#define GET_OFFSET(a) ((a)->IsNumber() ? (a)->IntegerValue() : -1) -#endif - // bytesWritten = write(fd, data, position, enc, callback) // Wrapper for write(2). // @@ -728,15 +738,23 @@ static Handle Write(const Arguments& args) { } ASSERT_OFFSET(args[4]); - off_t pos = GET_OFFSET(args[4]); + node_off_t pos = GET_OFFSET(args[4]); char * buf = (char*)buffer_data + off; Local cb = args[5]; if (cb->IsFunction()) { +#ifdef NODE_USE_64BIT_UV_FS_API + ASYNC_CALL(write64, cb, fd, buf, len, pos) +#else ASYNC_CALL(write, cb, fd, buf, len, pos) +#endif } else { +#ifdef NODE_USE_64BIT_UV_FS_API + SYNC_CALL(write64, 0, fd, buf, len, pos) +#else SYNC_CALL(write, 0, fd, buf, len, pos) +#endif return scope.Close(Integer::New(SYNC_RESULT)); } } @@ -765,7 +783,7 @@ static Handle Read(const Arguments& args) { Local cb; size_t len; - off_t pos; + node_off_t pos; char * buf = NULL; @@ -797,9 +815,17 @@ static Handle Read(const Arguments& args) { cb = args[5]; if (cb->IsFunction()) { +#ifdef NODE_USE_64BIT_UV_FS_API + ASYNC_CALL(read64, cb, fd, buf, len, pos); +#else ASYNC_CALL(read, cb, fd, buf, len, pos); +#endif } else { +#ifdef NODE_USE_64BIT_UV_FS_API + SYNC_CALL(read64, 0, fd, buf, len, pos) +#else SYNC_CALL(read, 0, fd, buf, len, pos) +#endif Local bytesRead = Integer::New(SYNC_RESULT); return scope.Close(bytesRead); } diff --git a/src/v8_typed_array.cc b/src/v8_typed_array.cc index 3cf2db00af..4a76f97059 100644 --- a/src/v8_typed_array.cc +++ b/src/v8_typed_array.cc @@ -471,6 +471,8 @@ class TypedArray { case v8::kExternalPixelArray: return "Uint8ClampedArray"; } abort(); + // Please the compiler + return ""; } }; @@ -567,7 +569,7 @@ int valueToCType(v8::Handle value) { template <> float valueToCType(v8::Handle value) { - return value->NumberValue(); + return static_cast(value->NumberValue()); } template <> diff --git a/test/disabled/test-fs-largefile.js b/test/simple/test-fs-largefile.js similarity index 98% rename from test/disabled/test-fs-largefile.js rename to test/simple/test-fs-largefile.js index 98238b00b8..ffd6261d87 100644 --- a/test/disabled/test-fs-largefile.js +++ b/test/simple/test-fs-largefile.js @@ -53,6 +53,6 @@ assert.ok(exceptionRaised); fs.close(fd); process.on('exit', function() { - fs.unlink(filepath); + fs.unlinkSync(filepath); }); diff --git a/test/simple/test-fs-readfile-unlink.js b/test/simple/test-fs-readfile-unlink.js new file mode 100644 index 0000000000..0bb4a67f78 --- /dev/null +++ b/test/simple/test-fs-readfile-unlink.js @@ -0,0 +1,48 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var assert = require('assert'), + common = require('../common'), + fs = require('fs'), + path = require('path'), + dirName = path.resolve(common.fixturesDir, 'test-readfile-unlink'), + fileName = path.resolve(dirName, 'test.bin'); + +var buf = new Buffer(512 * 1024); +buf.fill(42); + +try { + fs.mkdirSync(dirName); +} catch (e) { + // Ignore if the directory already exists. + if (e.code != 'EEXIST') throw e; +} + +fs.writeFileSync(fileName, buf); + +fs.readFile(fileName, function(err, data) { + assert.ifError(err); + assert(data.length == buf.length); + assert.strictEqual(buf[0], 42); + + fs.unlinkSync(fileName); + fs.rmdirSync(dirName); +}); diff --git a/test/simple/test-http-no-content-length.js b/test/simple/test-http-no-content-length.js new file mode 100644 index 0000000000..8c565aedc7 --- /dev/null +++ b/test/simple/test-http-no-content-length.js @@ -0,0 +1,46 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var common = require('../common'); +var assert = require('assert'); +var net = require('net'); +var http = require('http'); + +var body = ''; + +var server = net.createServer(function(socket) { + // Neither Content-Length nor Connection + socket.end('HTTP/1.1 200 ok\r\n\r\nHello'); +}).listen(common.PORT, function() { + var req = http.get({port: common.PORT}, function(res) { + res.setEncoding('utf8'); + res.on('data', function(chunk) { + body += chunk; + }); + res.on('end', function() { + server.close(); + }); + }); +}); + +process.on('exit', function() { + assert.equal(body, 'Hello'); +}); diff --git a/test/simple/test-memory-usage-emfile.js b/test/simple/test-memory-usage-emfile.js new file mode 100644 index 0000000000..aaed899530 --- /dev/null +++ b/test/simple/test-memory-usage-emfile.js @@ -0,0 +1,37 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + + + + +var common = require('../common'); +var assert = require('assert'); + +var fs = require('fs'); + +var files = []; + +while (files.length < 256) + files.push(fs.openSync(__filename, 'r')); + +var r = process.memoryUsage(); +console.log(common.inspect(r)); +assert.equal(true, r['rss'] > 0); diff --git a/test/simple/test-net-write-after-close.js b/test/simple/test-net-write-after-close.js index fd0d30d540..b77e9af724 100644 --- a/test/simple/test-net-write-after-close.js +++ b/test/simple/test-net-write-after-close.js @@ -24,18 +24,23 @@ var assert = require('assert'); var net = require('net'); var gotError = false; +var gotWriteCB = false; process.on('exit', function() { assert(gotError); + assert(gotWriteCB); }); var server = net.createServer(function(socket) { - setTimeout(function() { - assert.throws(function() { - socket.write('test'); - }, /This socket is closed/); + socket.on('error', function(error) { server.close(); gotError = true; + }); + + setTimeout(function() { + socket.write('test', function(e) { + gotWriteCB = true; + }); }, 250); });