@@ -353,6 +353,7 @@ class TestSnapshot(unittest.TestCase):
353353 DATABASE_NAME = INSTANCE_NAME + '/databases/' + DATABASE_ID
354354 SESSION_ID = 'session-id'
355355 SESSION_NAME = DATABASE_NAME + '/sessions/' + SESSION_ID
356+ TRANSACTION_ID = b'DEADBEEF'
356357
357358 def _getTargetClass (self ):
358359 from google .cloud .spanner .snapshot import Snapshot
@@ -493,12 +494,11 @@ def test_ctor_w_multi_use_and_exact_staleness(self):
493494 self .assertTrue (snapshot ._multi_use )
494495
495496 def test__make_txn_selector_w_transaction_id (self ):
496- TXN_ID = b'DEADBEEF'
497497 session = _Session ()
498498 snapshot = self ._make_one (session )
499- snapshot ._transaction_id = TXN_ID
499+ snapshot ._transaction_id = self . TRANSACTION_ID
500500 selector = snapshot ._make_txn_selector ()
501- self .assertEqual (selector .id , TXN_ID )
501+ self .assertEqual (selector .id , self . TRANSACTION_ID )
502502
503503 def test__make_txn_selector_strong (self ):
504504 session = _Session ()
@@ -579,6 +579,90 @@ def test__make_txn_selector_w_exact_staleness_w_multi_use(self):
579579 self .assertEqual (options .read_only .exact_staleness .seconds , 3 )
580580 self .assertEqual (options .read_only .exact_staleness .nanos , 123456000 )
581581
582+ def test_begin_wo_multi_use (self ):
583+ session = _Session ()
584+ snapshot = self ._make_one (session )
585+ with self .assertRaises (ValueError ):
586+ snapshot .begin ()
587+
588+ def test_begin_w_existing_txn_id (self ):
589+ session = _Session ()
590+ snapshot = self ._make_one (session , multi_use = True )
591+ snapshot ._transaction_id = self .TRANSACTION_ID
592+ with self .assertRaises (ValueError ):
593+ snapshot .begin ()
594+
595+ def test_begin_w_gax_error (self ):
596+ from google .gax .errors import GaxError
597+ from google .cloud ._helpers import _pb_timestamp_to_datetime
598+
599+ database = _Database ()
600+ api = database .spanner_api = _FauxSpannerAPI (
601+ _random_gax_error = True )
602+ timestamp = self ._makeTimestamp ()
603+ session = _Session (database )
604+ snapshot = self ._make_one (
605+ session , read_timestamp = timestamp , multi_use = True )
606+
607+ with self .assertRaises (GaxError ):
608+ snapshot .begin ()
609+
610+ session_id , txn_options , options = api ._begun
611+ self .assertEqual (session_id , session .name )
612+ self .assertEqual (
613+ _pb_timestamp_to_datetime (txn_options .read_only .read_timestamp ),
614+ timestamp )
615+ self .assertEqual (options .kwargs ['metadata' ],
616+ [('google-cloud-resource-prefix' , database .name )])
617+
618+ def test_begin_ok_exact_staleness (self ):
619+ from google .cloud .proto .spanner .v1 .transaction_pb2 import (
620+ Transaction as TransactionPB )
621+
622+ transaction_pb = TransactionPB (id = self .TRANSACTION_ID )
623+ database = _Database ()
624+ api = database .spanner_api = _FauxSpannerAPI (
625+ _begin_transaction_response = transaction_pb )
626+ duration = self ._makeDuration (seconds = 3 , microseconds = 123456 )
627+ session = _Session (database )
628+ snapshot = self ._make_one (
629+ session , exact_staleness = duration , multi_use = True )
630+
631+ txn_id = snapshot .begin ()
632+
633+ self .assertEqual (txn_id , self .TRANSACTION_ID )
634+ self .assertEqual (snapshot ._transaction_id , self .TRANSACTION_ID )
635+
636+ session_id , txn_options , options = api ._begun
637+ self .assertEqual (session_id , session .name )
638+ read_only = txn_options .read_only
639+ self .assertEqual (read_only .exact_staleness .seconds , 3 )
640+ self .assertEqual (read_only .exact_staleness .nanos , 123456000 )
641+ self .assertEqual (options .kwargs ['metadata' ],
642+ [('google-cloud-resource-prefix' , database .name )])
643+
644+ def test_begin_ok_exact_strong (self ):
645+ from google .cloud .proto .spanner .v1 .transaction_pb2 import (
646+ Transaction as TransactionPB )
647+
648+ transaction_pb = TransactionPB (id = self .TRANSACTION_ID )
649+ database = _Database ()
650+ api = database .spanner_api = _FauxSpannerAPI (
651+ _begin_transaction_response = transaction_pb )
652+ session = _Session (database )
653+ snapshot = self ._make_one (session , multi_use = True )
654+
655+ txn_id = snapshot .begin ()
656+
657+ self .assertEqual (txn_id , self .TRANSACTION_ID )
658+ self .assertEqual (snapshot ._transaction_id , self .TRANSACTION_ID )
659+
660+ session_id , txn_options , options = api ._begun
661+ self .assertEqual (session_id , session .name )
662+ self .assertTrue (txn_options .read_only .strong )
663+ self .assertEqual (options .kwargs ['metadata' ],
664+ [('google-cloud-resource-prefix' , database .name )])
665+
582666
583667class _Session (object ):
584668
@@ -593,7 +677,15 @@ class _Database(object):
593677
594678class _FauxSpannerAPI (_GAXBaseAPI ):
595679
596- _read_with = None
680+ _read_with = _begin = None
681+
682+ def begin_transaction (self , session , options_ , options = None ):
683+ from google .gax .errors import GaxError
684+
685+ self ._begun = (session , options_ , options )
686+ if self ._random_gax_error :
687+ raise GaxError ('error' )
688+ return self ._begin_transaction_response
597689
598690 # pylint: disable=too-many-arguments
599691 def streaming_read (self , session , table , columns , key_set ,
0 commit comments