使用promises并跳过代码时,Mocha测试会超时,为什么?(Mocha test times out when using promises and skips over code, why?)
我一直试图连续2天运行这个测试,我无法弄清楚它有什么问题:
/*eslint-env mocha */ // var expect = require('chai').expect; var chai = require('chai'); var chaiAsPromised = require("chai-as-promised"); var expect = chai.expect; var Promise = require('bluebird'); var Archive = require('../lib/archive'); var path = require('path'); var fs = Promise.promisifyAll(require('fs-extra')); var globAsync = Promise.promisify(require('glob')); var tar = require('tar-fs'); var zlib = Promise.promisifyAll(require('zlib')); chai.use(chaiAsPromised); describe('Archive', function() { var pkg; var archive_location; var subject; beforeEach(function() { pkg = { name: 'test_0790feebb1', recipient_name: 'Test', files: { letter: '../documents/letters/test/letter.tex', resume: '../documents/cover/cover.tex' }, compiled_files: { package: '../documents/letters/test/test.pdf' } }; archive_location = path.resolve('archives/test_0790feebb1.tar.gz'); subject = new Archive(pkg); }); after(function() { return globAsync('archives/test*') .each(function(filename) { return fs.removeAsync(filename); }); }); describe('#make', function() { it('has the correct directory structure', function() { // debugger; var tmp_extract_path = path.resolve('test/.tmp'); var tarPromise = function(data) { console.log('tarP'); // never run return new Promise(function(reject, resolve) { data .pipe(zlib.Unzip()) .pipe(tar.extract(tmp_extract_path)) .on('error', reject) .on('end', resolve); }); }; var verifyDir = function() { console.log('verD'); // never run return Promise.all([ 'code', 'pdf', 'code/repo', 'code/documents', 'code/documents/letters', 'code/documents/letters/test', 'code/documents/letters/shared', 'code/documents/cover', 'code/documents/letters' ].map(function(subpath) { return fs.statAsync(path.resolve(tmp_extract_path, subpath)); })); }; return fs.createReadStreamAsync(archive_location) .then(function(data) { return tarPromise(data); }) .then(function() { return verifyDir(); }) .then(function(files) { console.log(files); // never run return expect(true).to.be.true; }) .catch(function(e) { console.log(e); }); }); }); });
各种console.log甚至从未执行过,最终测试时间没有任何错误或堆栈跟踪。
我不知道我做错了什么,承诺现在伤害了我的大脑。 当我使用节点检查器运行代码并取消注释断点时,我可以看到
this._runnable._trace
值是"done() called multiple times"
。 我不知道这是否是一个实际的错误,也不知道如果这是一个错误,它不会抛出异常。 我无法解释为什么这甚至发生,因为我不再使用任何done()
回调和promises,我的测试以function()
开头而不是function(done)
就像异步测试一样有任何想法吗?
I have been trying to run this test for 2 days straight now and I can't figure what is wrong with it:
/*eslint-env mocha */ // var expect = require('chai').expect; var chai = require('chai'); var chaiAsPromised = require("chai-as-promised"); var expect = chai.expect; var Promise = require('bluebird'); var Archive = require('../lib/archive'); var path = require('path'); var fs = Promise.promisifyAll(require('fs-extra')); var globAsync = Promise.promisify(require('glob')); var tar = require('tar-fs'); var zlib = Promise.promisifyAll(require('zlib')); chai.use(chaiAsPromised); describe('Archive', function() { var pkg; var archive_location; var subject; beforeEach(function() { pkg = { name: 'test_0790feebb1', recipient_name: 'Test', files: { letter: '../documents/letters/test/letter.tex', resume: '../documents/cover/cover.tex' }, compiled_files: { package: '../documents/letters/test/test.pdf' } }; archive_location = path.resolve('archives/test_0790feebb1.tar.gz'); subject = new Archive(pkg); }); after(function() { return globAsync('archives/test*') .each(function(filename) { return fs.removeAsync(filename); }); }); describe('#make', function() { it('has the correct directory structure', function() { // debugger; var tmp_extract_path = path.resolve('test/.tmp'); var tarPromise = function(data) { console.log('tarP'); // never run return new Promise(function(reject, resolve) { data .pipe(zlib.Unzip()) .pipe(tar.extract(tmp_extract_path)) .on('error', reject) .on('end', resolve); }); }; var verifyDir = function() { console.log('verD'); // never run return Promise.all([ 'code', 'pdf', 'code/repo', 'code/documents', 'code/documents/letters', 'code/documents/letters/test', 'code/documents/letters/shared', 'code/documents/cover', 'code/documents/letters' ].map(function(subpath) { return fs.statAsync(path.resolve(tmp_extract_path, subpath)); })); }; return fs.createReadStreamAsync(archive_location) .then(function(data) { return tarPromise(data); }) .then(function() { return verifyDir(); }) .then(function(files) { console.log(files); // never run return expect(true).to.be.true; }) .catch(function(e) { console.log(e); }); }); }); });
The various console.log never even get executed and eventually the test times out without any error or stack trace.
I have no idea what I am doing wrong and promises hurt my brain now. When I run the code with node inspector and uncomment the breakpoint, I can see that he value of
this._runnable._trace
is"done() called multiple times"
. I have no idea if this is an actual error nor why it doesn't throw an exception if that's an error. I can't explain either why this is even happening since I am not using anydone()
callbacks anymore with promises and that my test starts withfunction()
and notfunction(done)
like an async test wouldAny ideas?
原文:https://stackoverflow.com/questions/32876127
最满意答案
如果你想学习汇编,我会认真地建议编写C或C ++代码并检查生成的程序集以便选择目标。
这会给你一个基础。
#include <cmath> double compute(double x, double degree, double radius) { return x + std::sin(degree) * radius; }
提供以下LLVM IR:
define double @_Z7computeddd(double %x, double %degree, double %radius) nounwind uwtable readnone { %1 = tail call double @sin(double %degree) nounwind readnone %2 = fmul double %1, %radius %3 = fadd double %2, %x ret double %3 } declare double @sin(double) nounwind readnone
这给出了以下组件:
.text .globl _Z7computeddd .align 16, 0x90 .type _Z7computeddd,@function _Z7computeddd: # @_Z7computeddd .Ltmp1: .cfi_startproc # BB#0: subq $24, %rsp .Ltmp2: .cfi_def_cfa_offset 32 movsd %xmm2, 16(%rsp) # 8-byte Spill movsd %xmm0, 8(%rsp) # 8-byte Spill movaps %xmm1, %xmm0 callq sin mulsd 16(%rsp), %xmm0 # 8-byte Folded Reload addsd 8(%rsp), %xmm0 # 8-byte Folded Reload addq $24, %rsp ret .Ltmp3: .size _Z7computeddd, .Ltmp3-_Z7computeddd .Ltmp4: .cfi_endproc .Leh_func_end0: .section ".note.GNU-stack","",@progbits
请注意,还有一个
sin
召唤。If you want to learn assembly, I would seriously recommend writing C or C++ code and inspecting the generated assembly for your target of choice.
This will give you a basis.
#include <cmath> double compute(double x, double degree, double radius) { return x + std::sin(degree) * radius; }
Gives the following LLVM IR:
define double @_Z7computeddd(double %x, double %degree, double %radius) nounwind uwtable readnone { %1 = tail call double @sin(double %degree) nounwind readnone %2 = fmul double %1, %radius %3 = fadd double %2, %x ret double %3 } declare double @sin(double) nounwind readnone
Which gives the following assembly:
.text .globl _Z7computeddd .align 16, 0x90 .type _Z7computeddd,@function _Z7computeddd: # @_Z7computeddd .Ltmp1: .cfi_startproc # BB#0: subq $24, %rsp .Ltmp2: .cfi_def_cfa_offset 32 movsd %xmm2, 16(%rsp) # 8-byte Spill movsd %xmm0, 8(%rsp) # 8-byte Spill movaps %xmm1, %xmm0 callq sin mulsd 16(%rsp), %xmm0 # 8-byte Folded Reload addsd 8(%rsp), %xmm0 # 8-byte Folded Reload addq $24, %rsp ret .Ltmp3: .size _Z7computeddd, .Ltmp3-_Z7computeddd .Ltmp4: .cfi_endproc .Leh_func_end0: .section ".note.GNU-stack","",@progbits
Note that there is still a
sin
call.
相关问答
更多-
如果你想学习汇编,我会认真地建议编写C或C ++代码并检查生成的程序集以便选择目标。 这会给你一个基础。 #include
double compute(double x, double degree, double radius) { return x + std::sin(degree) * radius; } 提供以下LLVM IR: define double @_Z7computeddd(double %x, double %degree, double %radius) ... -
C代码在Visual Studio中编译成什么汇编语言?(What assembly language does C code compile into in Visual Studio?)[2022-02-21]
它编译的代码不是汇编,而是直接的机器代码,至少在链接时优化之后。 您在调试时看到的是对当前正在执行的机器代码进行即时反汇编 。 因此,它没有额外的结构,比如标签,宏等,这样您就可以在高级汇编程序中找到它们,因为这些额外的信息在生成机器码时会丢失(或者,更准确地说,永远不会出现) 。 如果你的意思是语法,Visual Studio将显示Intel语法中的汇编指令,这与AT&T语法不同,这是GCC和GNU汇编程序的默认语法。 事实上,这也可能是胡言乱语。 如果jmp不对齐(x86指令是可变长度的),或者不包含可 ... -
使用C ++汇编语言(Assembly language with C++)[2022-05-24]
因为它是一个浮点数组,每个浮点数占4个字节,你应该将索引乘以4.还要注意C调用约定要求调用者释放参数,因此你的“ ret 8 ”是错误的。 mov eax, esi在最后是无关紧要的。 Since it's an array of floats each taking 4 bytes you should multiply the index by 4. Also note that C calling convention mandates that the caller will free the ar ... -
Doxygen和汇编语言(Doxygen and Assembly Language)[2024-03-05]
查看Doxygen FAQ的问题12。 你正在处理纯粹的汇编文件,还是C源代码中的内联汇编? 假设前者,你必须编写一个输入过滤器来将汇编代码转换成类C(更简单),或者编写新的解析器(更难)。 See question 12 of the Doxygen FAQ. Are you dealing with pure assembly files, or inline assembly inside C sources? Assuming the former, you'll have to either wr ... -
是的,大多数时候。 首先,从错误的假设开始,低级语言(本例中的程序集)总是会产生比高级语言(C ++和C在这种情况下)更快的代码。 这不是真的。 C代码总是比Java代码快吗? 不,因为有另一个变量:程序员。 编写代码和建筑细节知识的方式大大影响了性能(正如你在这种情况下看到的)。 您可以随时制作一个示例,其中手工汇编代码比编译代码更好,但通常它是虚构示例或单个例程,而不是500.000+行的C ++代码的真正程序)。 我认为编译器将生成更好的汇编代码95%, 有时候,只有少数时候,您可能需要为少数,短期, ...
-
将参数传递给gcdasm() 两个int参数通过寄存器传递,而不是堆栈。 第一个和第二个参数分别在rdi和rsi的下半部分(即: edi和esi )中传递。 因此,通过将edi和esi分别扩展为rax和rbx ,可以将传递的参数加载到这些寄存器中: movsx rax, edi ;load rax with x movsx rbx, esi ;load rbx with y 但是请注意, rbx不是一个临时寄存器 ,因此被调用者需要在修改它之前保存它,然后在离开gcdasm函数之前恢复它。 你可以简单 ...
-
它不需要,但大部分都是这样做的,因为可以将相同的汇编程序(程序)用于C / C ++ /任意汇编器编译器的输出。 例如,g ++首先生成汇编代码(可以使用-S开关查看生成的汇编程序)。 MSVC也是这样( /FAs )。 It doesn't have to, but most do it anyway, as the same assembler (program) can be used for the output of the C/C++/whatever-to-assembler compiler ...
-
#if defined(_MSC_VER) // visual c #elif defined(__GCCE__) // gcce #else // unknown #endif 我的内联汇编程序技能很生疏,但它的工作原理如下: __asm { // some assembler code } 但只要使用rdtsc,你就可以使用内在函数: unsigned __int64 counter; counter = __rdtsc(); http://msdn.microsoft.com/en-us/lib ...
-
让我们分解一下: .file "delta.c" 编译器使用它来告诉程序集来自的源文件。 这对汇编程序来说并不重要。 .section .rodata 这开始一个新的部分。 “rodata”是“只读数据”部分的名称。 本部分最终将数据写入将内存映射为只读数据的可执行文件。 可执行映像的所有“.rodata”页面最终都将由加载映像的所有进程共享。 通常,源代码中的任何“编译时常量”都无法被优化到汇编内部函数中,最终将被存储在“只读数据段”中。 .LC0: .string "%d" .L ...
-
@ modelnine的注释是正确的 - lea用于简化循环中的赋值。 你有: x = ii - 2; 并且lea (加载有效地址)指令正在有效地执行: esi = &(*(eax - 2)); &和*相互抵消(这很重要 - 在这种情况下取消引用eax可能会导致问题),所以你得到: esi = eax - 2; 正是你的C代码试图做的事情。 @modelnine's comment is correct - the lea is being used to simplify the assignmen ...