test.js 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718
  1. /* globals describe, it, before, after */
  2. /* eslint no-loop-func:0 guard-for-in:0 */
  3. // no spam
  4. var logging = require("../lib/logging");
  5. if (process.env.VERBOSE_TEST !== "true" && process.env.TRAVIS !== "true") {
  6. logging.log = logging.debug = logging.warn = logging.error = function() {};
  7. }
  8. var networking = require("../lib/networking");
  9. var helpers = require("../lib/helpers");
  10. var request = require("request");
  11. var config = require("../config");
  12. var server = require("../lib/server");
  13. var assert = require("assert");
  14. var skins = require("../lib/skins");
  15. var cache = require("../lib/cache");
  16. var crc = require("crc").crc32;
  17. var fs = require("fs");
  18. // we don't want tests to fail because of slow internet
  19. config.server.http_timeout *= 3;
  20. var uuids = fs.readFileSync("test/uuids.txt").toString().split(/\r?\n/);
  21. // Get a random UUIDto prevent rate limiting
  22. var uuid = uuids[Math.round(Math.random() * (uuids.length - 1))];
  23. // Let's hope these will never be assigned
  24. var steve_ids = [
  25. "fffffff0" + "fffffff0" + "fffffff0" + "fffffff0",
  26. "fffffff0" + "fffffff0" + "fffffff1" + "fffffff1",
  27. "fffffff0" + "fffffff1" + "fffffff0" + "fffffff1",
  28. "fffffff0" + "fffffff1" + "fffffff1" + "fffffff0",
  29. "fffffff1" + "fffffff0" + "fffffff0" + "fffffff1",
  30. "fffffff1" + "fffffff0" + "fffffff1" + "fffffff0",
  31. "fffffff1" + "fffffff1" + "fffffff0" + "fffffff0",
  32. "fffffff1" + "fffffff1" + "fffffff1" + "fffffff1",
  33. ];
  34. // Let's hope these will never be assigned
  35. var alex_ids = [
  36. "fffffff0" + "fffffff0" + "fffffff0" + "fffffff1",
  37. "fffffff0" + "fffffff0" + "fffffff1" + "fffffff0",
  38. "fffffff0" + "fffffff1" + "fffffff0" + "fffffff0",
  39. "fffffff0" + "fffffff1" + "fffffff1" + "fffffff1",
  40. "fffffff1" + "fffffff0" + "fffffff0" + "fffffff0",
  41. "fffffff1" + "fffffff0" + "fffffff1" + "fffffff1",
  42. "fffffff1" + "fffffff1" + "fffffff0" + "fffffff1",
  43. "fffffff1" + "fffffff1" + "fffffff1" + "fffffff0",
  44. ];
  45. // generates a 12 character random string
  46. function rid() {
  47. return Math.random().toString(36).substring(2, 14);
  48. }
  49. function getRandomInt(min, max) {
  50. return Math.floor(Math.random() * (max - min + 1)) + min;
  51. }
  52. describe("Crafatar", function() {
  53. // we might have to make 2 HTTP requests
  54. this.timeout(config.server.http_timeout * 2 + 50);
  55. before(function(done) {
  56. console.log("Flushing and waiting for redis ...");
  57. cache.get_redis().flushall(function() {
  58. console.log("Redis flushed!");
  59. done();
  60. });
  61. });
  62. describe("UUID/username", function() {
  63. it("non-hex uuid is invalid", function(done) {
  64. assert.strictEqual(helpers.id_valid("g098cb60fa8e427cb299793cbd302c9a"), false);
  65. done();
  66. });
  67. it("empty id is invalid", function(done) {
  68. assert.strictEqual(helpers.id_valid(""), false);
  69. done();
  70. });
  71. it("lowercase uuid is valid", function(done) {
  72. assert.strictEqual(helpers.id_valid("0098cb60fa8e427cb299793cbd302c9a"), true);
  73. done();
  74. });
  75. it("uppercase uuid is valid", function(done) {
  76. assert.strictEqual(helpers.id_valid("1DCEF164FF0A47F2B9A691385C774EE7"), true);
  77. done();
  78. });
  79. it("dashed uuid is valid", function(done) {
  80. assert.strictEqual(helpers.id_valid("0098cb60-fa8e-427c-b299-793cbd302c9a"), true);
  81. done();
  82. });
  83. it("username is invalid", function(done) {
  84. assert.strictEqual(helpers.id_valid("__niceUs3rname__"), false);
  85. done();
  86. });
  87. it("username alex is invalid", function(done) {
  88. assert.strictEqual(helpers.id_valid("alex"), false);
  89. done();
  90. });
  91. it("username mhf_alex is invalid", function(done) {
  92. assert.strictEqual(helpers.id_valid("mhf_alex"), false);
  93. done();
  94. });
  95. it("username steve is invalid", function(done) {
  96. assert.strictEqual(helpers.id_valid("steve"), false);
  97. done();
  98. });
  99. it("username mhf_steve is invalid", function(done) {
  100. assert.strictEqual(helpers.id_valid("mhf_steve"), false);
  101. done();
  102. });
  103. it(">16 length username is invalid", function(done) {
  104. assert.strictEqual(helpers.id_valid("ThisNameIsTooLong"), false);
  105. done();
  106. });
  107. it("should not exist (uuid)", function(done) {
  108. var number = getRandomInt(0, 9).toString();
  109. networking.get_profile(rid(), Array(33).join(number), function(err, profile) {
  110. assert.ifError(err);
  111. assert.strictEqual(profile, null);
  112. done();
  113. });
  114. });
  115. });
  116. describe("Avatar", function() {
  117. for (var a in alex_ids) {
  118. var alexid = alex_ids[a];
  119. (function(alex_id) {
  120. it("UUID " + alex_id + " should default to MHF_Alex", function(done) {
  121. assert.strictEqual(skins.default_skin(alex_id), "mhf_alex");
  122. done();
  123. });
  124. }(alexid));
  125. }
  126. for (var s in steve_ids) {
  127. var steveid = steve_ids[s];
  128. (function(steve_id) {
  129. it("UUID " + steve_id + " should default to MHF_Steve", function(done) {
  130. assert.strictEqual(skins.default_skin(steve_id), "mhf_steve");
  131. done();
  132. });
  133. }(steveid));
  134. }
  135. });
  136. describe("Errors", function() {
  137. it("should time out on uuid info download", function(done) {
  138. var original_timeout = config.server.http_timeout;
  139. config.server.http_timeout = 1;
  140. networking.get_profile(rid(), "069a79f444e94726a5befca90e38aaf5", function(err, profile) {
  141. assert.notStrictEqual(["ETIMEDOUT", "ESOCKETTIMEDOUT"].indexOf(err.code), -1);
  142. config.server.http_timeout = original_timeout;
  143. done();
  144. });
  145. });
  146. it("should time out on skin download", function(done) {
  147. var original_timeout = config.http_timeout;
  148. config.server.http_timeout = 1;
  149. networking.get_from(rid(), "http://textures.minecraft.net/texture/477be35554684c28bdeee4cf11c591d3c88afb77e0b98da893fd7bc318c65184", function(body, res, error) {
  150. assert.notStrictEqual(["ETIMEDOUT", "ESOCKETTIMEDOUT"].indexOf(error.code), -1);
  151. config.server.http_timeout = original_timeout;
  152. done();
  153. });
  154. });
  155. it("should not find the skin", function(done) {
  156. assert.doesNotThrow(function() {
  157. networking.get_from(rid(), "http://textures.minecraft.net/texture/this-does-not-exist", function(img, response, err) {
  158. assert.strictEqual(err, null); // no error here, but it shouldn't throw exceptions
  159. done();
  160. });
  161. });
  162. });
  163. it("should not find the file", function(done) {
  164. skins.open_skin(rid(), "non/existent/path", function(err, img) {
  165. assert(err);
  166. done();
  167. });
  168. });
  169. });
  170. describe("Server", function() {
  171. // throws Exception when default headers are not in res.headers
  172. function assert_headers(res) {
  173. assert(res.headers["content-type"]);
  174. assert("" + res.headers["response-time"]);
  175. assert(res.headers["x-request-id"]);
  176. assert.equal(res.headers["access-control-allow-origin"], "*");
  177. assert.equal(res.headers["cache-control"], "max-age=" + config.caching.browser);
  178. }
  179. // throws Exception when +url+ is requested with +etag+
  180. // and it does not return 304 without a body
  181. function assert_cache(url, etag, callback) {
  182. request.get(url, {
  183. headers: {
  184. "If-None-Match": etag,
  185. },
  186. }, function(error, res, body) {
  187. assert.ifError(error);
  188. assert.strictEqual(body, '');
  189. assert.equal(res.statusCode, 304);
  190. assert_headers(res);
  191. callback();
  192. });
  193. }
  194. before(function(done) {
  195. server.boot(function() {
  196. done();
  197. });
  198. });
  199. it("should return 405 Method Not Allowed for POST", function(done) {
  200. request.post("http://localhost:3000", function(error, res, body) {
  201. assert.ifError(error);
  202. assert.strictEqual(res.statusCode, 405);
  203. done();
  204. });
  205. });
  206. it("should return correct HTTP response for home page", function(done) {
  207. var url = "http://localhost:3000";
  208. request.get(url, function(error, res, body) {
  209. assert.ifError(error);
  210. assert.strictEqual(res.statusCode, 200);
  211. assert_headers(res);
  212. assert(res.headers.etag);
  213. assert.strictEqual(res.headers["content-type"], "text/html; charset=utf-8");
  214. assert.strictEqual(res.headers.etag, '"' + crc(body) + '"');
  215. assert(body);
  216. assert_cache(url, res.headers.etag, function() {
  217. done();
  218. });
  219. });
  220. });
  221. it("should return correct HTTP response for assets", function(done) {
  222. var url = "http://localhost:3000/stylesheets/style.css";
  223. request.get(url, function(error, res, body) {
  224. assert.ifError(error);
  225. assert.strictEqual(res.statusCode, 200);
  226. assert_headers(res);
  227. assert(res.headers.etag);
  228. assert.strictEqual(res.headers["content-type"], "text/css");
  229. assert.strictEqual(res.headers.etag, '"' + crc(body) + '"');
  230. assert(body);
  231. assert_cache(url, res.headers.etag, function() {
  232. done();
  233. });
  234. });
  235. });
  236. it("should return correct HTTP response for URL encoded URLs", function(done) {
  237. var url = "http://localhost:3000/%61%76%61%74%61%72%73/%61%65%37%39%35%61%61%38%36%33%32%37%34%30%38%65%39%32%61%62%32%35%63%38%61%35%39%66%33%62%61%31"; // avatars/ae795aa86327408e92ab25c8a59f3ba1
  238. request.get(url, function(error, res, body) {
  239. assert.ifError(error);
  240. assert.strictEqual(res.statusCode, 201);
  241. assert_headers(res);
  242. assert(res.headers.etag);
  243. assert.strictEqual(res.headers["content-type"], "image/png");
  244. assert(body);
  245. done();
  246. });
  247. });
  248. it("should not fail on simultaneous requests", function(done) {
  249. var url = "http://localhost:3000/avatars/696a82ce41f44b51aa31b8709b8686f0";
  250. // 10 requests at once
  251. var requests = 10;
  252. var finished = 0;
  253. function partDone() {
  254. finished++;
  255. if (requests === finished) {
  256. done();
  257. }
  258. }
  259. function req() {
  260. request.get(url, function(error, res, body) {
  261. assert.ifError(error);
  262. assert.strictEqual(res.statusCode === 201 || res.statusCode === 200, true);
  263. assert_headers(res);
  264. assert(res.headers.etag);
  265. assert.strictEqual(res.headers["content-type"], "image/png");
  266. assert(body);
  267. partDone();
  268. });
  269. }
  270. // make simultanous requests
  271. for (var k = 0; k < requests; k++) {
  272. req(k);
  273. }
  274. });
  275. var server_tests = {
  276. "avatar with existing uuid": {
  277. url: "http://localhost:3000/avatars/853c80ef3c3749fdaa49938b674adae6?size=16",
  278. crc32: [3337292777],
  279. },
  280. "avatar with non-existent uuid": {
  281. url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16",
  282. crc32: [2416827277, 1243826040],
  283. },
  284. "avatar with non-existent uuid defaulting to mhf_alex": {
  285. url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=mhf_alex",
  286. crc32: [862751081, 809395677],
  287. },
  288. "avatar with non-existent uuid defaulting to uuid": {
  289. url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=853c80ef3c3749fdaa49938b674adae6",
  290. crc32: [0],
  291. redirect: "/avatars/853c80ef3c3749fdaa49938b674adae6?size=16",
  292. },
  293. "avatar with non-existent uuid defaulting to url": {
  294. url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
  295. crc32: [0],
  296. redirect: "http://example.com/CaseSensitive",
  297. },
  298. "overlay avatar with existing uuid": {
  299. url: "http://localhost:3000/avatars/853c80ef3c3749fdaa49938b674adae6?size=16&overlay",
  300. crc32: [1710265722],
  301. },
  302. "overlay avatar with non-existent uuid": {
  303. url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&overlay",
  304. crc32: [2416827277, 1243826040],
  305. },
  306. "overlay avatar with non-existent uuid defaulting to mhf_alex": {
  307. url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&overlay&default=mhf_alex",
  308. crc32: [862751081, 809395677],
  309. },
  310. "overlay avatar with non-existent uuid defaulting to uuid": {
  311. url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=853c80ef3c3749fdaa49938b674adae6",
  312. crc32: [0],
  313. redirect: "/avatars/853c80ef3c3749fdaa49938b674adae6?size=16",
  314. },
  315. "overlay avatar with non-existent uuid defaulting to url": {
  316. url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&overlay&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
  317. crc32: [0],
  318. redirect: "http://example.com/CaseSensitive",
  319. },
  320. "cape with existing uuid": {
  321. url: "http://localhost:3000/capes/853c80ef3c3749fdaa49938b674adae6",
  322. crc32: [2556702429],
  323. },
  324. "cape with non-existent uuid": {
  325. url: "http://localhost:3000/capes/00000000000000000000000000000000",
  326. crc32: [0],
  327. },
  328. "cape with non-existent uuid defaulting to url": {
  329. url: "http://localhost:3000/capes/00000000000000000000000000000000?default=http%3A%2F%2Fexample.com%2FCaseSensitive",
  330. crc32: [0],
  331. redirect: "http://example.com/CaseSensitive",
  332. },
  333. "skin with existing uuid": {
  334. url: "http://localhost:3000/skins/853c80ef3c3749fdaa49938b674adae6",
  335. crc32: [26500336],
  336. },
  337. "skin with non-existent uuid": {
  338. url: "http://localhost:3000/skins/00000000000000000000000000000000",
  339. crc32: [981937087],
  340. },
  341. "skin with non-existent uuid defaulting to mhf_alex": {
  342. url: "http://localhost:3000/skins/00000000000000000000000000000000?default=mhf_alex",
  343. crc32: [2298915739],
  344. },
  345. "skin with non-existent uuid defaulting to uuid": {
  346. url: "http://localhost:3000/skins/00000000000000000000000000000000?size=16&default=853c80ef3c3749fdaa49938b674adae6",
  347. crc32: [0],
  348. redirect: "/skins/853c80ef3c3749fdaa49938b674adae6?size=16",
  349. },
  350. "skin with non-existent uuid defaulting to url": {
  351. url: "http://localhost:3000/skins/00000000000000000000000000000000?default=http%3A%2F%2Fexample.com%2FCaseSensitive",
  352. crc32: [0],
  353. redirect: "http://example.com/CaseSensitive",
  354. },
  355. "head render with existing uuid": {
  356. url: "http://localhost:3000/renders/head/853c80ef3c3749fdaa49938b674adae6?scale=2",
  357. crc32: [1168786201],
  358. },
  359. "head render with non-existent uuid": {
  360. url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2",
  361. crc32: [3800926063],
  362. },
  363. "head render with non-existent uuid defaulting to mhf_alex": {
  364. url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&default=mhf_alex",
  365. crc32: [4027858557],
  366. },
  367. "head render with non-existent uuid defaulting to uuid": {
  368. url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&default=853c80ef3c3749fdaa49938b674adae6",
  369. crc32: [0],
  370. redirect: "/renders/head/853c80ef3c3749fdaa49938b674adae6?scale=2",
  371. },
  372. "head render with non-existent uuid defaulting to url": {
  373. url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
  374. crc32: [0],
  375. redirect: "http://example.com/CaseSensitive",
  376. },
  377. "overlay head render with existing uuid": {
  378. url: "http://localhost:3000/renders/head/853c80ef3c3749fdaa49938b674adae6?scale=2&overlay",
  379. crc32: [2880579826],
  380. },
  381. "overlay head render with non-existent uuid": {
  382. url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&overlay",
  383. crc32: [3800926063],
  384. },
  385. "overlay head render with non-existent uuid defaulting to mhf_alex": {
  386. url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&overlay&default=mhf_alex",
  387. crc32: [4027858557],
  388. },
  389. "overlay head with non-existent uuid defaulting to uuid": {
  390. url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&overlay&default=853c80ef3c3749fdaa49938b674adae6",
  391. crc32: [0],
  392. redirect: "/renders/head/853c80ef3c3749fdaa49938b674adae6?scale=2&overlay=",
  393. },
  394. "overlay head render with non-existent uuid defaulting to url": {
  395. url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&overlay&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
  396. crc32: [0],
  397. redirect: "http://example.com/CaseSensitive",
  398. },
  399. "body render with existing uuid": {
  400. url: "http://localhost:3000/renders/body/853c80ef3c3749fdaa49938b674adae6?scale=2",
  401. crc32: [2745192436],
  402. },
  403. "body render with non-existent uuid": {
  404. url: "http://localhost:3000/renders/body/00000000000000000000000000000000?scale=2",
  405. crc32: [996962526],
  406. },
  407. "body render with non-existent uuid defaulting to mhf_alex": {
  408. url: "http://localhost:3000/renders/body/00000000000000000000000000000000?scale=2&default=mhf_alex",
  409. crc32: [1255106465],
  410. },
  411. "body render with non-existent uuid defaulting to uuid": {
  412. url: "http://localhost:3000/renders/body/00000000000000000000000000000000?scale=2&default=853c80ef3c3749fdaa49938b674adae6",
  413. crc32: [0],
  414. redirect: "/renders/body/853c80ef3c3749fdaa49938b674adae6?scale=2",
  415. },
  416. "body render with non-existent uuid defaulting to url": {
  417. url: "http://localhost:3000/renders/body/00000000000000000000000000000000?scale=2&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
  418. crc32: [0],
  419. redirect: "http://example.com/CaseSensitive",
  420. },
  421. "overlay body render with existing uuid": {
  422. url: "http://localhost:3000/renders/body/853c80ef3c3749fdaa49938b674adae6?scale=2&overlay",
  423. crc32: [2441671793],
  424. },
  425. "overlay body render with non-existent uuid": {
  426. url: "http://localhost:3000/renders/body/00000000000000000000000000000000?scale=2&overlay",
  427. crc32: [996962526],
  428. },
  429. "overlay body render with non-existent uuid defaulting to mhf_alex": {
  430. url: "http://localhost:3000/renders/body/00000000000000000000000000000000?scale=2&overlay&default=mhf_alex",
  431. crc32: [1255106465],
  432. },
  433. "overlay body render with non-existent uuid defaulting to url": {
  434. url: "http://localhost:3000/renders/body/00000000000000000000000000000000?scale=2&overlay&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
  435. crc32: [0],
  436. redirect: "http://example.com/CaseSensitive",
  437. },
  438. };
  439. for (var description in server_tests) {
  440. var loc = server_tests[description];
  441. (function(location) {
  442. it("should return correct HTTP response for " + description, function(done) {
  443. request.get(location.url, {followRedirect: false, encoding: null}, function(error, res, body) {
  444. assert.ifError(error);
  445. assert_headers(res);
  446. assert(res.headers["x-storage-type"]);
  447. var hash = crc(body);
  448. var matches = false;
  449. for (var c = 0; c < location.crc32.length; c++) {
  450. if (location.crc32[c] === hash) {
  451. matches = true;
  452. break;
  453. }
  454. }
  455. try {
  456. assert(matches);
  457. } catch(e) {
  458. throw new Error(hash + " != " + location.crc32 + " | " + body.toString("base64"));
  459. }
  460. assert.strictEqual(res.headers.location, location.redirect);
  461. if (location.crc32[0] === 0) {
  462. assert.strictEqual(res.statusCode, location.redirect ? 307 : 404);
  463. assert.ifError(res.headers.etag); // etag must not be present on non-200
  464. assert.strictEqual(res.headers["content-type"], "text/plain");
  465. done();
  466. } else {
  467. assert.strictEqual(res.headers["content-type"], "image/png");
  468. assert.strictEqual(res.statusCode, res.headers["x-storage-type"] === "downloaded" ? 201 : 200);
  469. assert(res.headers.etag);
  470. assert.strictEqual(res.headers.etag, '"' + hash + '"');
  471. assert_cache(location.url, res.headers.etag, function() {
  472. done();
  473. });
  474. }
  475. });
  476. });
  477. }(loc));
  478. }
  479. it("should return 304 on server error", function(done) {
  480. var original_debug = config.server.debug_enabled;
  481. var original_timeout = config.server.http_timeout;
  482. config.server.debug_enabled = false;
  483. config.server.http_timeout = 1;
  484. request.get({url: "http://localhost:3000/avatars/0000000000000000000000000000000f", headers: {"If-None-Match": '"some-etag"'}}, function(error, res, body) {
  485. assert.ifError(error);
  486. assert.strictEqual(body, '');
  487. assert.strictEqual(res.statusCode, 304);
  488. config.server.debug_enabled = original_debug;
  489. config.server.http_timeout = original_timeout;
  490. done();
  491. });
  492. });
  493. it("should return a 422 (invalid size)", function(done) {
  494. var size = config.avatars.max_size + 1;
  495. request.get("http://localhost:3000/avatars/2d5aa9cdaeb049189930461fc9b91cc5?size=" + size, function(error, res, body) {
  496. assert.ifError(error);
  497. assert.strictEqual(res.statusCode, 422);
  498. done();
  499. });
  500. });
  501. it("should return a 422 (invalid scale)", function(done) {
  502. var scale = config.renders.max_scale + 1;
  503. request.get("http://localhost:3000/renders/head/2d5aa9cdaeb049189930461fc9b91cc5?scale=" + scale, function(error, res, body) {
  504. assert.ifError(error);
  505. assert.strictEqual(res.statusCode, 422);
  506. done();
  507. });
  508. });
  509. it("should return a 422 (invalid render type)", function(done) {
  510. request.get("http://localhost:3000/renders/invalid/Jake_0", function(error, res, body) {
  511. assert.ifError(error);
  512. assert.strictEqual(res.statusCode, 422);
  513. done();
  514. });
  515. });
  516. // testing all paths for Invalid UUID
  517. var locations = ["avatars", "skins", "capes", "renders/body", "renders/head"];
  518. for (var l in locations) {
  519. loc = locations[l];
  520. (function(location) {
  521. it("should return a 422 (invalid uuid " + location + ")", function(done) {
  522. request.get("http://localhost:3000/" + location + "/thisisaninvaliduuid", function(error, res, body) {
  523. assert.ifError(error);
  524. assert.strictEqual(res.statusCode, 422);
  525. done();
  526. });
  527. });
  528. it("should return a 404 (invalid path " + location + ")", function(done) {
  529. request.get("http://localhost:3000/" + location + "/853c80ef3c3749fdaa49938b674adae6/invalid", function(error, res, body) {
  530. assert.ifError(error);
  531. assert.strictEqual(res.statusCode, 404);
  532. done();
  533. });
  534. });
  535. }(loc));
  536. }
  537. });
  538. // we have to make sure that we test both a 32x64 and 64x64 skin
  539. describe("Networking: Render", function() {
  540. it("should not fail (uuid, 32x64 skin)", function(done) {
  541. helpers.get_render(rid(), "af74a02d19cb445bb07f6866a861f783", 6, true, true, function(err, hash, img) {
  542. assert.strictEqual(err, null);
  543. done();
  544. });
  545. });
  546. it("should not fail (uuid, 64x64 skin)", function(done) {
  547. helpers.get_render(rid(), "2d5aa9cdaeb049189930461fc9b91cc5", 6, true, true, function(err, hash, img) {
  548. assert.strictEqual(err, null);
  549. done();
  550. });
  551. });
  552. });
  553. describe("Networking: Cape", function() {
  554. it("should not fail (guaranteed cape)", function(done) {
  555. helpers.get_cape(rid(), "Dinnerbone", function(err, hash, status, img) {
  556. assert.strictEqual(err, null);
  557. done();
  558. });
  559. });
  560. it("should already exist", function(done) {
  561. before(function() {
  562. cache.get_redis().flushall();
  563. });
  564. helpers.get_cape(rid(), "Dinnerbone", function(err, hash, status, img) {
  565. assert.strictEqual(err, null);
  566. done();
  567. });
  568. });
  569. it("should not be found", function(done) {
  570. helpers.get_cape(rid(), "Jake_0", function(err, hash, status, img) {
  571. assert.ifError(err);
  572. assert.strictEqual(img, null);
  573. done();
  574. });
  575. });
  576. });
  577. describe("Networking: Skin", function() {
  578. it("should not fail", function(done) {
  579. helpers.get_cape(rid(), "Jake_0", function(err, hash, status, img) {
  580. assert.strictEqual(err, null);
  581. done();
  582. });
  583. });
  584. it("should already exist", function(done) {
  585. before(function() {
  586. cache.get_redis().flushall();
  587. });
  588. helpers.get_cape(rid(), "Jake_0", function(err, hash, status, img) {
  589. assert.strictEqual(err, null);
  590. done();
  591. });
  592. });
  593. });
  594. describe("Networking: Avatar", function() {
  595. before(function() {
  596. cache.get_redis().flushall();
  597. });
  598. it("should be downloaded", function(done) {
  599. helpers.get_avatar(rid(), uuid, false, 160, function(err, status, image) {
  600. assert.ifError(err);
  601. assert.strictEqual(status, 2);
  602. done();
  603. });
  604. });
  605. it("should be cached", function(done) {
  606. helpers.get_avatar(rid(), uuid, false, 160, function(err, status, image) {
  607. assert.ifError(err);
  608. assert.strictEqual(status === 0 || status === 1, true);
  609. done();
  610. });
  611. });
  612. });
  613. describe("Networking: Skin", function() {
  614. it("should not fail (uuid)", function(done) {
  615. helpers.get_skin(rid(), uuid, function(err, hash, status, img) {
  616. assert.strictEqual(err, null);
  617. done();
  618. });
  619. });
  620. });
  621. describe("Networking: Render", function() {
  622. it("should not fail (full body)", function(done) {
  623. helpers.get_render(rid(), uuid, 6, true, true, function(err, hash, img) {
  624. assert.ifError(err);
  625. done();
  626. });
  627. });
  628. it("should not fail (only head)", function(done) {
  629. helpers.get_render(rid(), uuid, 6, true, false, function(err, hash, img) {
  630. assert.ifError(err);
  631. done();
  632. });
  633. });
  634. });
  635. describe("Networking: Cape", function() {
  636. it("should not fail (possible cape)", function(done) {
  637. helpers.get_cape(rid(), uuid, function(err, hash, status, img) {
  638. assert.ifError(err);
  639. done();
  640. });
  641. });
  642. });
  643. describe("Errors", function() {
  644. before(function() {
  645. cache.get_redis().flushall();
  646. });
  647. it("uuid SHOULD be rate limited", function(done) {
  648. networking.get_profile(rid(), uuid, function() {
  649. networking.get_profile(rid(), uuid, function(err, profile) {
  650. assert.strictEqual(err.toString(), "HTTP: 429");
  651. assert.strictEqual(profile, null);
  652. done();
  653. });
  654. });
  655. });
  656. it("CloudFront rate limit is handled", function(done) {
  657. var original_rate_limit = config.server.sessions_rate_limit;
  658. config.server.sessions_rate_limit = 1;
  659. networking.get_profile(rid(), uuid, function() {
  660. networking.get_profile(rid(), uuid, function(err, profile) {
  661. assert.strictEqual(err.code, "RATELIMIT");
  662. config.server.sessions_rate_limit = original_rate_limit;
  663. done();
  664. });
  665. });
  666. });
  667. });
  668. after(function(done) {
  669. server.close(function() {
  670. cache.get_redis().quit();
  671. done();
  672. });
  673. });
  674. });