'example.org','utm'=>(object)[]]));chown($site.'/config.json','fixture'); $ssh=new phpseclib3\Net\SSH2('127.0.0.1',2222);$key=$ssh->getServerPublicHostKey();check(is_string($key),'real SSH host key available'); $sftpTarget=$store->saveTarget(['id'=>'sftp','name'=>'SFTP fixture','domain'=>'fixture.invalid','type'=>'sftp','host'=>'127.0.0.1','port'=>2222,'user'=>'fixture','host_key'=>$key,'root'=>$site,'enabled'=>true],'fixture-only-password'); $store->verifyTarget('sftp');$sftpTarget=$store->target('sftp');$remote=new Transport($store,$sftpTarget); $remote->test();check(true,'real SSH remote lock and permission preflight');$remoteRead=$remote->readConfig();check($remoteRead['config']->host==='example.org','real SSH config read'); $remote->writeConfig($remoteRead['version'],Config::encode((object)['host'=>'ssh-written.example','utm'=>(object)[]]));check($remote->readConfig()['config']->host==='ssh-written.example','real SSH atomic CAS and reread'); rejects(fn()=>$remote->writeConfig($remoteRead['version'],Config::encode((object)['host'=>'stale.example'])),'real remote stale version rejected'); $bad=$sftpTarget;$bad['host_key']='SHA256:'.str_repeat('A',43);rejects(fn()=>(new Transport($store,$bad))->test(),'pinned SSH key mismatch rejected before login'); // Восстановить проверенный набор после намеренной порчи формата security-тестом. $preparedRemote=$sets->prepareZip($zipPath,1);$sets->upload($sftpTarget,1,$preparedRemote,'SFTP проверка');check(is_file($site.'/1/01_desk_1-source.jpg'),'real SFTP image transfer, remote activation, checksum and decode'); // Реальный обрыв ожидания после удалённой записи: fixture задерживает завершение команды. $wrapper=<<<'SH' #!/bin/sh /usr/bin/php "$@" if [ -f /home/fixture/delay-next-write ]; then op=$(/usr/bin/php -r '$p=json_decode(base64_decode($argv[1]),true);echo $p["op"]??"";' "$5") if [ "$op" = write ]; then rm /home/fixture/delay-next-write; sleep 3; fi fi SH; file_put_contents('/usr/local/bin/php',$wrapper);chmod('/usr/local/bin/php',0755); $beforeTimeout=$remote->readConfig();$timeoutJob=$jobs->create('apply',['targets'=>[['id'=>'sftp','version'=>$beforeTimeout['version']]],'changes'=>[['path'=>['host'],'value'=>'timeout-written.example']]]); file_put_contents('/home/fixture/delay-next-write','1');chown('/home/fixture/delay-next-write','fixture');putenv('ADMIN_TRANSPORT_TIMEOUT=1');$jobs->run($timeoutJob['id']); check($jobs->get($timeoutJob['id'])['results'][0]['status']==='unknown','real SSH timeout after write persists unknown result'); putenv('ADMIN_TRANSPORT_TIMEOUT=60');$jobs->retry($timeoutJob['id'],['sftp']);$jobs->run($timeoutJob['id']);$retried=$jobs->get($timeoutJob['id']);check($retried['results'][0]['status']==='success','retry reads committed hash after real transport timeout'); echo "SFTP integration complete\n";