'This helper will setup a multiphase chunked PUT request and yield at
the context at the commit phase (after getting the second expect-100
continue response.
It can setup a reasonable stub request, but you can over-ride some
characteristics of the request via kwargs.
:param test_doc: first part of the mime conversation before the object
server will send the 100-continue, this includes the
object body
:param headers: headers to send along with the initial request; some
object-metadata (e.g.  X-Backend-Obj-Content-Length)
is generally expected to match the test_doc)
:param finish_body: boolean, if true send "0
" after test_doc
and wait for 100-continue before yielding context'

@contextmanager
def _check_multiphase_put_commit_handling(self, test_doc=None, headers=None, finish_body=True):

    test_data = encode_frag_archive_bodies(POLICIES[1], 'obj    data')[0]
    footer_meta = {'X-Object-Sysmeta-Ec-Frag-Index': '2', 'Etag': md5(test_data).hexdigest()}
    footer_json = json.dumps(footer_meta)
    footer_meta_cksum = md5(footer_json).hexdigest()
    test_doc = (test_doc or '\r\n'.join(('--boundary123', 'X-Document:    object    body', '', test_data, '--boundary123', 'X-Document:    object    metadata', ('Content-MD5:    ' + footer_meta_cksum), '', footer_json, '--boundary123')))
    headers = (headers or {'Content-Type': 'text/plain', 'Transfer-Encoding': 'chunked', 'Expect': '100-continue', 'X-Backend-Storage-Policy-Index': '1', 'X-Backend-Obj-Content-Length': len(test_data), 'X-Backend-Obj-Metadata-Footer': 'yes', 'X-Backend-Obj-Multipart-Mime-Boundary': 'boundary123', 'X-Backend-Obj-Multiphase-Commit': 'yes'})
    put_timestamp = utils.Timestamp(headers.setdefault('X-Timestamp', utils.Timestamp.now().internal))
    container_update = 'swift.obj.server.ObjectController.container_update'
    with mock.patch(container_update) as _container_update:
        conn = bufferedhttp.http_connect('127.0.0.1', self.port, 'sda1', '0', 'PUT', '/a/c/o', headers=headers)
        resp = conn.getexpect()
        self.assertEqual(resp.status, 100)
        expect_headers = HeaderKeyDict(resp.getheaders())
        to_send = ('%x\r\n%s\r\n' % (len(test_doc), test_doc))
        conn.send(to_send)
        if finish_body:
            conn.send('0\r\n\r\n')
            resp = conn.getexpect()
            self.assertEqual(resp.status, 100)
        (yield {'conn': conn, 'expect_headers': expect_headers, 'put_timestamp': put_timestamp, 'mock_container_update': _container_update})
    sleep(0.1)
