// This is a simple end to end test that makes sure a master using log // storage with ZooKeeper can successfully launch a task. TEST_F(RegistrarZooKeeperTest, TaskRunning) { Try<Owned<cluster::Master>> master = StartMaster(); ASSERT_SOME(master); MockExecutor exec(DEFAULT_EXECUTOR_ID); TestContainerizer containerizer(&exec); Owned<MasterDetector> detector = master.get()->createDetector(); Try<Owned<cluster::Slave>> slave = StartSlave(detector.get(), &containerizer); ASSERT_SOME(slave); MockScheduler sched; MesosSchedulerDriver driver( &sched, DEFAULT_FRAMEWORK_INFO, master.get()->pid, DEFAULT_CREDENTIAL); EXPECT_CALL(sched, registered(&driver, _, _)); Future<vector<Offer>> offers; EXPECT_CALL(sched, resourceOffers(&driver, _)) .WillOnce(FutureArg<1>(&offers)) .WillRepeatedly(Return()); // Ignore subsequent offers. driver.start(); AWAIT_READY(offers); EXPECT_NE(0u, offers->size()); TaskInfo task = createTask(offers.get()[0], "dummy", DEFAULT_EXECUTOR_ID); EXPECT_CALL(exec, registered(_, _, _, _)); EXPECT_CALL(exec, launchTask(_, _)) .WillOnce(SendStatusUpdateFromTask(TASK_RUNNING)); Future<Nothing> resourcesUpdated; EXPECT_CALL(containerizer, update(_, Resources(offers.get()[0].resources()))) .WillOnce(DoAll(FutureSatisfy(&resourcesUpdated), Return(Nothing()))); Future<TaskStatus> status; EXPECT_CALL(sched, statusUpdate(&driver, _)) .WillOnce(FutureArg<1>(&status)); driver.launchTasks(offers.get()[0].id(), {task}); AWAIT_READY(status); EXPECT_EQ(TASK_RUNNING, status->state()); AWAIT_READY(resourcesUpdated); EXPECT_CALL(exec, shutdown(_)) .Times(AtMost(1)); driver.stop(); driver.join(); }
// This test verifies that when the scheduler calls stop() before // abort(), no pending acknowledgements are sent. TEST_F(MesosSchedulerDriverTest, DropAckIfStopCalledBeforeAbort) { Try<PID<Master>> master = StartMaster(); ASSERT_SOME(master); MockExecutor exec(DEFAULT_EXECUTOR_ID); TestContainerizer containerizer(&exec); Try<PID<Slave>> slave = StartSlave(&containerizer); ASSERT_SOME(slave); MockScheduler sched; MesosSchedulerDriver driver( &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL); EXPECT_CALL(sched, registered(&driver, _, _)); EXPECT_CALL(sched, resourceOffers(&driver, _)) .WillOnce(LaunchTasks(DEFAULT_EXECUTOR_INFO, 1, 1, 16, "*")) .WillRepeatedly(Return()); // Ignore subsequent offers. // When an update is received, stop the driver and then abort it. Future<Nothing> statusUpdate; EXPECT_CALL(sched, statusUpdate(&driver, _)) .WillOnce(DoAll(StopAndAbort(), FutureSatisfy(&statusUpdate))); // Ensure no status update acknowledgements are sent from the driver // to the master. EXPECT_NO_FUTURE_CALLS( mesos::scheduler::Call(), mesos::scheduler::Call::ACKNOWLEDGE, _ , master.get()); EXPECT_CALL(exec, registered(_, _, _, _)); EXPECT_CALL(exec, launchTask(_, _)) .WillOnce(SendStatusUpdateFromTask(TASK_RUNNING)); EXPECT_CALL(exec, shutdown(_)) .Times(AtMost(1)); driver.start(); AWAIT_READY(statusUpdate); // Settle the clock to ensure driver finishes processing the status // update and sends acknowledgement if necessary. In this test it // shouldn't send an acknowledgement. Clock::pause(); Clock::settle(); driver.stop(); driver.join(); Shutdown(); }
TEST_F(test_bootup, get_socket_failure) { InSequence dummy; m_addrinfo.ai_next = NULL; EXPECT_FUNCTION_CALL(m_getaddrinfo, (_, _, _, _)).WillOnce(DoAll(SetArgPointee<3>(&m_addrinfo), Return(0))); EXPECT_FUNCTION_CALL(m_socket, (_, _, _)).WillOnce(Return(-1)); EXPECT_FUNCTION_CALL(m_freeaddrinfo, (&m_addrinfo)); EXPECT_EQ(1, server(stderr, stdout, 2000, 0, 32)); }
TEST_F(V4L2ControlDelegateTest, SetSuccess) { uint8_t input = 10; int32_t conversion_result = 99; EXPECT_CALL(*mock_converter_, MetadataToV4L2(input, _)) .WillOnce(DoAll(SetArgPointee<1>(conversion_result), Return(0))); EXPECT_CALL(*mock_device_, SetControl(control_id_, conversion_result, _)) .WillOnce(Return(0)); ASSERT_EQ(dut_->SetValue(input), 0); }
TEST_F(TaggedControlOptionsTest, DefaultValue) { uint8_t value = 99; int template_id = 3; EXPECT_CALL(*mock_options_, DefaultValueForTemplate(template_id, _)) .WillOnce(DoAll(SetArgPointee<1>(value), Return(0))); PrepareDUT(); uint8_t actual = value + 1; EXPECT_EQ(dut_->DefaultValueForTemplate(template_id, &actual), 0); EXPECT_EQ(actual, value); }
TEST_F(V4L2ControlDelegateTest, GetConverterFailure) { int32_t device_result = 99; EXPECT_CALL(*mock_device_, GetControl(control_id_, _)) .WillOnce(DoAll(SetArgPointee<1>(device_result), Return(0))); int err = -99; EXPECT_CALL(*mock_converter_, V4L2ToMetadata(device_result, _)) .WillOnce(Return(err)); uint8_t unused = 1; ASSERT_EQ(dut_->GetValue(&unused), err); }
// This test ensures that destroy can be called at the end of the // launch loop. The composing containerizer still calls the // underlying containerizer's destroy (because it's not sure // if the containerizer can handle the type of container being // launched). If the launch is not supported by any containerizers // both the launch and destroy futures should be false. TEST_F(ComposingContainerizerTest, DestroyAfterLaunchLoop) { vector<Containerizer*> containerizers; MockContainerizer* mockContainerizer1 = new MockContainerizer(); containerizers.push_back(mockContainerizer1); ComposingContainerizer containerizer(containerizers); ContainerID containerId; containerId.set_value("container"); TaskInfo taskInfo; ExecutorInfo executorInfo; SlaveID slaveId; std::map<std::string, std::string> environment; Promise<bool> launchPromise; EXPECT_CALL(*mockContainerizer1, launch(_, _, _, _, _, _, _, _)) .WillOnce(Return(launchPromise.future())); Future<Nothing> destroy; Promise<bool> destroyPromise; EXPECT_CALL(*mockContainerizer1, destroy(_)) .WillOnce(DoAll(FutureSatisfy(&destroy), Return(destroyPromise.future()))); Future<bool> launched = containerizer.launch( containerId, taskInfo, executorInfo, "dir", "user", slaveId, environment, false); Resources resources = Resources::parse("cpus:1;mem:256").get(); EXPECT_TRUE(launched.isPending()); Future<bool> destroyed = containerizer.destroy(containerId); // We make sure the destroy is being called on the containerizer. AWAIT_READY(destroy); launchPromise.set(false); destroyPromise.set(false); // `launch` should return false and `destroyed` should return false // because none of the containerizers support the launch. AWAIT_EXPECT_EQ(false, launched); AWAIT_EXPECT_EQ(false, destroyed); }
void expectPushPromiseAndHeaders( MockHTTPTransaction& pushTxn, uint8_t pri, HTTPPushTransactionHandler**pushHandlerPtr) { EXPECT_CALL(m_txn, newPushedTransaction(_)) .WillOnce(DoAll(SaveArg<0>(pushHandlerPtr), Return(&pushTxn))); EXPECT_CALL(pushTxn, sendHeaders(_)) .WillOnce(Invoke([pri] (const HTTPMessage& promise) { EXPECT_TRUE(promise.isRequest()); EXPECT_EQ(promise.getPriority(), pri); EXPECT_EQ(promise.getHeaders().getSingleOrEmpty("hello"), std::string("world")); })) .WillOnce(Invoke([] (const HTTPMessage& response) { EXPECT_TRUE(response.isResponse()); })); }
// Tests that an agent endpoint handler forms // correct queries against the authorizer. TEST_P(SlaveEndpointTest, AuthorizedRequest) { const string endpoint = GetParam(); StandaloneMasterDetector detector; MockAuthorizer mockAuthorizer; Try<Owned<cluster::Slave>> agent = StartSlave(&detector, &mockAuthorizer); ASSERT_SOME(agent); Future<authorization::Request> request; EXPECT_CALL(mockAuthorizer, authorized(_)) .WillOnce(DoAll(FutureArg<0>(&request), Return(true))); Future<Response> response = http::get( agent.get()->pid, endpoint, None(), createBasicAuthHeaders(DEFAULT_CREDENTIAL)); AWAIT_READY(request); const string principal = DEFAULT_CREDENTIAL.principal(); EXPECT_EQ(principal, request.get().subject().value()); // TODO(bbannier): Once agent endpoint handlers use more than just // `GET_ENDPOINT_WITH_PATH` we should factor out the request method // and expected authorization action and parameterize // `SlaveEndpointTest` on that as well in addition to the endpoint. EXPECT_EQ(authorization::GET_ENDPOINT_WITH_PATH, request.get().action()); EXPECT_EQ("/" + endpoint, request.get().object().value()); AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response) << response.get().body; }
// This test has been temporarily disabled due to MESOS-1257. TEST_F(ExternalContainerizerTest, DISABLED_Launch) { Try<PID<Master> > master = this->StartMaster(); ASSERT_SOME(master); Flags testFlags; slave::Flags flags = this->CreateSlaveFlags(); flags.isolation = "external"; flags.containerizer_path = testFlags.build_dir + "/src/examples/python/test-containerizer"; MockExternalContainerizer containerizer(flags); Try<PID<Slave> > slave = this->StartSlave(&containerizer, flags); ASSERT_SOME(slave); MockScheduler sched; MesosSchedulerDriver driver( &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL); Future<FrameworkID> frameworkId; EXPECT_CALL(sched, registered(&driver, _, _)) .WillOnce(FutureArg<1>(&frameworkId)); Future<vector<Offer> > offers; EXPECT_CALL(sched, resourceOffers(&driver, _)) .WillOnce(FutureArg<1>(&offers)) .WillRepeatedly(Return()); // Ignore subsequent offers. driver.start(); AWAIT_READY(frameworkId); AWAIT_READY(offers); EXPECT_NE(0u, offers.get().size()); TaskInfo task; task.set_name("isolator_test"); task.mutable_task_id()->set_value("1"); task.mutable_slave_id()->CopyFrom(offers.get()[0].slave_id()); task.mutable_resources()->CopyFrom(offers.get()[0].resources()); Resources resources(offers.get()[0].resources()); Option<Bytes> mem = resources.mem(); ASSERT_SOME(mem); Option<double> cpus = resources.cpus(); ASSERT_SOME(cpus); const std::string& file = path::join(flags.work_dir, "ready"); // This task induces user/system load in a child process by // running top in a child process for ten seconds. task.mutable_command()->set_value( #ifdef __APPLE__ // Use logging mode with 30,000 samples with no interval. "top -l 30000 -s 0 2>&1 > /dev/null & " #else // Batch mode, with 30,000 samples with no interval. "top -b -d 0 -n 30000 2>&1 > /dev/null & " #endif "touch " + file + "; " // Signals that the top command is running. "sleep 60"); Future<TaskStatus> status; EXPECT_CALL(sched, statusUpdate(&driver, _)) .WillOnce(FutureArg<1>(&status)) .WillRepeatedly(Return()); // Ignore rest for now. Future<ContainerID> containerId; EXPECT_CALL(containerizer, launch(_, _, _, _, _, _, _, _)) .WillOnce(DoAll(FutureArg<0>(&containerId), Invoke(&containerizer, &MockExternalContainerizer::_launch))); driver.launchTasks(offers.get()[0].id(), {task}); AWAIT_READY(containerId); AWAIT_READY(status); EXPECT_EQ(TASK_RUNNING, status.get().state()); // Wait for the task to begin inducing cpu time. while (!os::exists(file)); ExecutorID executorId; executorId.set_value(task.task_id().value()); // We'll wait up to 10 seconds for the child process to induce // 1/8 of a second of user and system cpu time in total. // TODO(bmahler): Also induce rss memory consumption, by re-using // the balloon framework. ResourceStatistics statistics; Duration waited = Duration::zero(); do { Future<ResourceStatistics> usage = containerizer.usage(containerId.get()); AWAIT_READY(usage); statistics = usage.get(); // If we meet our usage expectations, we're done! // NOTE: We are currently getting dummy-data from the test- // containerizer python script matching these expectations. // TODO(tillt): Consider working with real data. if (statistics.cpus_user_time_secs() >= 0.120 && statistics.cpus_system_time_secs() >= 0.05 && statistics.mem_rss_bytes() >= 1024u) { break; } os::sleep(Milliseconds(100)); waited += Milliseconds(100); } while (waited < Seconds(10)); EXPECT_GE(statistics.cpus_user_time_secs(), 0.120); EXPECT_GE(statistics.cpus_system_time_secs(), 0.05); EXPECT_EQ(statistics.cpus_limit(), cpus.get()); EXPECT_GE(statistics.mem_rss_bytes(), 1024u); EXPECT_EQ(statistics.mem_limit_bytes(), mem.get().bytes()); EXPECT_CALL(sched, statusUpdate(&driver, _)) .WillOnce(FutureArg<1>(&status)); driver.killTask(task.task_id()); AWAIT_READY(status); EXPECT_EQ(TASK_KILLED, status.get().state()); driver.stop(); driver.join(); this->Shutdown(); }
// This test ensures that destroy can be called while in the // launch loop. The composing containerizer still calls the // underlying containerizer's destroy (because it's not sure // if the containerizer can handle the type of container being // launched). If the launch is not supported by the 1st containerizer, // the composing containerizer should stop the launch loop and // set the value of destroy future to true. TEST_F(ComposingContainerizerTest, DestroyDuringUnsupportedLaunchLoop) { vector<Containerizer*> containerizers; MockContainerizer* mockContainerizer1 = new MockContainerizer(); MockContainerizer* mockContainerizer2 = new MockContainerizer(); containerizers.push_back(mockContainerizer1); containerizers.push_back(mockContainerizer2); ComposingContainerizer containerizer(containerizers); ContainerID containerId; containerId.set_value("container"); TaskInfo taskInfo; ExecutorInfo executorInfo; SlaveID slaveId; std::map<std::string, std::string> environment; Promise<bool> launchPromise; EXPECT_CALL(*mockContainerizer1, launch(_, _, _, _, _, _, _, _)) .WillOnce(Return(launchPromise.future())); Future<Nothing> destroy; Promise<bool> destroyPromise; EXPECT_CALL(*mockContainerizer1, destroy(_)) .WillOnce(DoAll(FutureSatisfy(&destroy), Return(destroyPromise.future()))); Future<bool> launched = containerizer.launch( containerId, taskInfo, executorInfo, "dir", "user", slaveId, environment, false); Resources resources = Resources::parse("cpus:1;mem:256").get(); EXPECT_TRUE(launched.isPending()); Future<bool> destroyed = containerizer.destroy(containerId); EXPECT_CALL(*mockContainerizer2, launch(_, _, _, _, _, _, _, _)) .Times(0); // We make sure the destroy is being called on the first containerizer. // The second containerizer shouldn't be called as well since the // container is already destroyed. AWAIT_READY(destroy); launchPromise.set(false); destroyPromise.set(false); // `launched` should be a failure and `destroyed` should be true // because the launch was stopped from being tried on the 2nd // containerizer because of the destroy. AWAIT_FAILED(launched); AWAIT_EXPECT_EQ(true, destroyed); }
/*---------------------------------------------------------------------------------------------- Crawl through the database and rename/delete the given styles. ----------------------------------------------------------------------------------------------*/ STDMETHODIMP FwDbMergeStyles::Process(DWORD hWnd) { BEGIN_COM_METHOD; Assert(m_vstuOldNames.Size() == m_vstuNewNames.Size()); if (!m_hvoRoot) return E_UNEXPECTED; if (!m_pclsidApp) return E_UNEXPECTED; if (LogFile()) { ULONG cbLog; StrAnsi staLog; staLog.Format("Changing style names in %S (%S)%n", DbName().Chars(), ServerName().Chars()); LogFile()->Write(staLog.Chars(), staLog.Length(), &cbLog); } m_qprog->DoModeless((HWND)hWnd); StrUni stuMsg(kstidChgStyleLabel); m_qprog->put_Title(stuMsg.Bstr()); ResetConnection(); BeginTrans(); CreateCommand(); SetPercentComplete(0); // We want to affect only a subset of the formatting and style information in the database, // based on which program is currently running, since different programs may be using // different sets of styles. This information is derived from m_hvoRoot and m_pclsidApp. // (Unfortunately, there's no way to derive one of these values from the other one.) The // current scheme works for Data Notebook, List Editor, TE, and LexText. Additional // programs may introduce even more complexities. // 1. Find all the owners of StStyle objects. This should match up to LangProject (Data // Notebook and List Editor), Scripture (TE), or LexDb (LexText). // 2. If an owner equals m_hvoRoot, then only those objects owned by m_hvoRoot have the // string and paragraph formatting fixed. Except that LexText also wants to fix all the // Text objects owned by the LangProject in addition to all the objects owned by the // LexDb, so those have to be added to the collection of objects. // 3. If none of the owners equals m_hvoRoot, we must be dealing with Data Notebook or List // Editor, which share a common set of styles owned by the LangProject itself. In // this case, we want all the objects owned by the LangProject except those owned by // another owner of styles (or the LangProject Text objects, since those use the // LexText styles even though they're not owned by the root object). (This isn't quite // right if either TE or LexText does not actually own any styles yet, but we won't worry // about this nicety.) // 4. After creating a temp table containing just the ids of those objects of interest, we // can then process all the relevant string formatting (via a string crawler) and // paragraph StyleRules (later in this method) // 5. Finally, we may need to fix the Style fields of the relevant UserViewField objects. // These are limited by the psclsidApp argument, since the UserView objects are specific // to specific applications. If pssclidApp indicates either Data Notebook or List // Editor, then UserViewField objects belonging to both of those programs are fixed. // Otherwise, only those UserViewField objects belonging to the specific program // identified by psclsidApp are fixed. ComBool fMoreRows; UINT cbSpaceTaken; ComBool fIsNull; int hobj = 0; int clid = 0; bool fFixOwned = false; int clidOwned = 0; int hvoLangProj = 0; Vector<int> vhvoOwners; Vector<int> vclidOwners; Vector<int> vhvoTexts; StrUni stuCmd; stuCmd.Format(L"SELECT DISTINCT c.Owner$, co.Class$ " L"FROM CmObject c " L"JOIN CmObject co on co.Id = c.Owner$ " L"WHERE c.Class$ = %d", kclidStStyle); CheckHr(GetOleDbCommand()->ExecCommand(stuCmd.Bstr(), knSqlStmtSelectWithOneRowset)); CheckHr(GetOleDbCommand()->GetRowset(0)); CheckHr(GetOleDbCommand()->NextRow(&fMoreRows)); while (fMoreRows) { CheckHr(GetOleDbCommand()->GetColValue(1, reinterpret_cast <BYTE *>(&hobj), isizeof(hobj), &cbSpaceTaken, &fIsNull, 0)); CheckHr(GetOleDbCommand()->GetColValue(2, reinterpret_cast <BYTE *>(&clid), isizeof(clid), &cbSpaceTaken, &fIsNull, 0)); if (hobj == m_hvoRoot) { fFixOwned = true; clidOwned = clid; } else if (clid == kclidLangProject) { hvoLangProj = hobj; } else { vhvoOwners.Push(hobj); vclidOwners.Push(clid); } CheckHr(GetOleDbCommand()->NextRow(&fMoreRows)); } Assert(hvoLangProj != 0); // This may not be defined in any of our header files. #ifndef kclidLexDb #define kclidLexDb 5005 #endif if (!fFixOwned || clidOwned == kclidLexDb) { // We need the set of LangProject_Texts objects to include or exclude. stuCmd.Format(L"SELECT Dst FROM LangProject_Texts WHERE Src = %d", hvoLangProj); CheckHr(GetOleDbCommand()->ExecCommand(stuCmd.Bstr(), knSqlStmtSelectWithOneRowset)); CheckHr(GetOleDbCommand()->GetRowset(0)); CheckHr(GetOleDbCommand()->NextRow(&fMoreRows)); while (fMoreRows) { CheckHr(GetOleDbCommand()->GetColValue(1, reinterpret_cast <BYTE *>(&hobj), isizeof(hobj), &cbSpaceTaken, &fIsNull, 0)); vhvoTexts.Push(hobj); CheckHr(GetOleDbCommand()->NextRow(&fMoreRows)); } } // Note that dbo.fnGetOwnedObjects$() returns the root object as the first row. stuCmd.Format(L"CREATE TABLE #OwnedObjIdsTbl%n" L"(%n" L" ObjId int not null%n" L")%n" L"CREATE CLUSTERED INDEX #OwnedObjIdsTblObjId ON #OwnedObjIdsTbl ([ObjId])%n"); CheckHr(GetOleDbCommand()->ExecCommand(stuCmd.Bstr(), knSqlStmtNoResults)); const OLECHAR * kpszDefTableFmt = L"INSERT INTO #OwnedObjIdsTbl%n" L"SELECT ObjId%n" L"FROM dbo.fnGetOwnedObjects$('%d', null, 0, 0, 1, null, 0)"; if (fFixOwned) { stuCmd.Format(kpszDefTableFmt, m_hvoRoot); stuCmd.FormatAppend(L";%n"); if (vhvoTexts.Size()) { stuCmd.FormatAppend( L"INSERT INTO #OwnedObjIdsTbl%n" L"SELECT ObjId%n" L"FROM dbo.fnGetOwnedObjects$('"); for (int ihvo = 0; ihvo < vhvoTexts.Size(); ++ihvo) if (ihvo == 0) stuCmd.FormatAppend(L"%d", vhvoTexts[ihvo]); else stuCmd.FormatAppend(L",%d", vhvoTexts[ihvo]); stuCmd.FormatAppend(L"', null, 0, 0, 1, null, 0);"); } } else { /* POSSIBLE SPEED ENHANCEMENT -------------------------- SELECT co.Id FROM CmObject co WHERE co.Owner$=1 AND co.OwnFlid$ NOT IN (6001006, 6001014, 6001040) gives a list of ids which own what we want to look through. This could then be handled by the following query, which runs in one-half to one-third of the time required by the current code. SELECT 1 UNION SELECT ObjId FROM dbo.fnGetOwnedObjects$('2,54728', null, 0, 0, 1, null, 0) whether the C++ code or the SQL code should put together the XML string is a good question. */ // REVIEW (SteveMiller): The temp tables below just slow things down. stuCmd.Clear(); if (vhvoOwners.Size() || vhvoTexts.Size()) { stuCmd.FormatAppend(L"CREATE TABLE #tblUnwanted ( ObjId int not null );%n"); stuCmd.FormatAppend(L"INSERT INTO #tblUnwanted%n"); stuCmd.FormatAppend(L"SELECT ObjId%n"); stuCmd.FormatAppend(L"FROM dbo.fnGetOwnedObjects$('"); for (int ihvo = 0; ihvo < vhvoOwners.Size(); ++ihvo) if (ihvo == 0) stuCmd.FormatAppend(L"%d", vhvoOwners[ihvo]); else stuCmd.FormatAppend(L",%d", vhvoOwners[ihvo]); for (int ihvo = 0; ihvo < vhvoTexts.Size(); ++ihvo) if (vhvoOwners.Size() < 0) // I don't think we can have an ownerless text, but hey... stuCmd.FormatAppend(L"%d", vhvoTexts[ihvo]); else stuCmd.FormatAppend(L",%d", vhvoTexts[ihvo]); stuCmd.FormatAppend(L"',null,0,0,1,null,0);%n"); } stuCmd.FormatAppend(kpszDefTableFmt, hvoLangProj); if (vhvoOwners.Size() || vhvoTexts.Size()) { stuCmd.FormatAppend(L"WHERE ObjId NOT IN (SELECT ObjId FROM #tblUnwanted);%n"); stuCmd.FormatAppend(L"DROP TABLE #tblUnwanted"); } stuCmd.FormatAppend(L";%n"); // terminate for Firebird } CheckHr(GetOleDbCommand()->ExecCommand(stuCmd.Bstr(), knSqlStmtNoResults)); // Do the standard stuff for monolingual and multilingual strings. DoAll(kstidChgStylePhaseOne, kstidChgStylePhaseTwo, false, // don't create a new transaction--this method handles it L"#OwnedObjIdsTbl"); // Fix all the StyleRules of instances of StPara. stuMsg.Load(kstidChgStylePhaseThree); m_qprog->put_Message(stuMsg.Bstr()); int nPercent = 0; SetPercentComplete(nPercent); Vector<int> vhobjFix; Vector<Vector<byte> > vvbFmtFix; vhobjFix.Clear(); vvbFmtFix.Clear(); Vector<byte> vbFmt; int cbFmt; ITsPropsFactoryPtr qtpf; qtpf.CreateInstance(CLSID_TsPropsFactory); int cRows; StrUni stuCmdCnt; stuCmdCnt.Format(L"SELECT COUNT(*) FROM StPara a%n" L"JOIN #OwnedObjIdsTbl b on b.ObjId = a.Id%n" L"WHERE a.StyleRules IS NOT NULL", m_hvoRoot); CheckHr(GetOleDbCommand()->ExecCommand(stuCmdCnt.Bstr(), knSqlStmtSelectWithOneRowset)); CheckHr(GetOleDbCommand()->GetRowset(0)); CheckHr(GetOleDbCommand()->NextRow(&fMoreRows)); CheckHr(GetOleDbCommand()->GetColValue(1, reinterpret_cast <BYTE *>(&cRows), isizeof(hobj), &cbSpaceTaken, &fIsNull, 0)); stuCmd.Format(L"SELECT a.Id, a.StyleRules FROM StPara a%n" L"JOIN #OwnedObjIdsTbl b on b.ObjId = a.Id%n" L"WHERE a.StyleRules IS NOT NULL", m_hvoRoot); CheckHr(GetOleDbCommand()->ExecCommand(stuCmd.Bstr(), knSqlStmtSelectWithOneRowset)); CheckHr(GetOleDbCommand()->GetRowset(0)); CheckHr(GetOleDbCommand()->NextRow(&fMoreRows)); int iRow = 0; ComVector<ITsTextProps> vqttp; vqttp.Resize(1); while (fMoreRows) { CheckHr(GetOleDbCommand()->GetColValue(1, reinterpret_cast <BYTE *>(&hobj), isizeof(hobj), &cbSpaceTaken, &fIsNull, 0)); CheckHr(GetOleDbCommand()->GetColValue(2, reinterpret_cast <BYTE *>(vbFmt.Begin()), vbFmt.Size(), &cbSpaceTaken, &fIsNull, 0)); cbFmt = cbSpaceTaken; if (cbFmt >= vbFmt.Size()) { vbFmt.Resize(cbFmt + 1); CheckHr(GetOleDbCommand()->GetColValue(2, reinterpret_cast <BYTE *>(vbFmt.Begin()), vbFmt.Size(), &cbSpaceTaken, &fIsNull, 0)); cbFmt = cbSpaceTaken; } vbFmt.Resize(cbFmt); ITsTextPropsPtr qttp; bool fModify = false; int cb = vbFmt.Size(); CheckHr(qtpf->DeserializePropsRgb(vbFmt.Begin(), &cb, (ITsTextProps **)&qttp)); // use a vector with exactly 1 item vqttp[0] = qttp; // Note: using "Normal" doesn't work all the time. For more complex scenarios where the // default style depends on the context of the deleted style, a replace should be done // instead of a delete. See FwStylesDlg.DeleteAndRenameStylesInDB() in FwStylesDlg.cs. fModify = ProcessFormatting(vqttp, g_pszwStyleNormal); if (fModify) { vhobjFix.Push(hobj); int cbNeeded; HRESULT hr; CheckHr(hr = vqttp[0]->SerializeRgb(vbFmt.Begin(), vbFmt.Size(), &cbNeeded)); if (hr == S_FALSE) { vbFmt.Resize(cbNeeded); hr = vqttp[0]->SerializeRgb(vbFmt.Begin(), vbFmt.Size(), &cbNeeded); } vbFmt.Resize(cbNeeded); vvbFmtFix.Push(vbFmt); } CheckHr(GetOleDbCommand()->NextRow(&fMoreRows)); iRow++; SetPercentComplete((iRow * 50) / cRows); } int ceFix = vhobjFix.Size(); SetPercentComplete(50); for (int ieFix = 0; ieFix < ceFix; ++ieFix) { stuCmd.Format(L"UPDATE StPara SET StyleRules=? WHERE [Id] = %d", vhobjFix[ieFix]); // Set the parameter and execute the command. CheckHr(GetOleDbCommand()->SetParameter(1, DBPARAMFLAGS_ISINPUT, NULL, DBTYPE_BYTES, reinterpret_cast<BYTE *>(vvbFmtFix[ieFix].Begin()), vvbFmtFix[ieFix].Size())); CheckHr(GetOleDbCommand()->ExecCommand(stuCmd.Bstr(), knSqlStmtNoResults)); SetPercentComplete(50 + ((ieFix * 50) / ceFix)); } SetPercentComplete(100); stuCmd.Assign(L"DROP TABLE #OwnedObjIdsTbl"); CheckHr(GetOleDbCommand()->ExecCommand(stuCmd.Bstr(), knSqlStmtNoResults)); // Fix style names in the view specs. // SQL gives us the power to just rename all items in one query. But that // won't correctly handle the situation of, for instance, renaming A to B, B to C, and // C to A. So we fix one item at a time and then update the database. static const GUID clsidNotebook = // {39886581-4DD5-11D4-8078-0000C0FB81B5} { 0x39886581, 0x4DD5, 0x11D4, { 0x80, 0x78, 0x00, 0x00, 0xC0, 0xFB, 0x81, 0xB5 } }; static GUID clsidListEditor = // {5EA62D01-7A78-11D4-8078-0000C0FB81B5} { 0x5EA62D01, 0x7A78, 0x11D4, { 0x80, 0x78, 0x00, 0x00, 0xC0, 0xFB, 0x81, 0xB5 } }; StrUni stuBaseCmd; stuBaseCmd.Format(L"%nFROM UserViewField a%n" L"JOIN UserViewRec_Fields uf on uf.Dst = a.Id%n" L"JOIN UserView_Records ur on ur.Dst = uf.Src%n" L"JOIN UserView uv on uv.Id = ur.Src%n" L"WHERE a.Style IS NOT NULL AND"); if (*m_pclsidApp == clsidNotebook || *m_pclsidApp == clsidListEditor) { Assert(!fFixOwned); stuBaseCmd.FormatAppend(L"%n\tuv.App in ('%g','%g')", &clsidNotebook, &clsidListEditor); } else { Assert(fFixOwned); stuBaseCmd.FormatAppend(L" uv.App = '%g'", m_pclsidApp); } stuMsg.Load(kstidChgStylePhaseFour); m_qprog->put_Message(stuMsg.Bstr()); SetPercentComplete(0); OLECHAR rgch[1024]; vhobjFix.Clear(); Vector<StrUni> vstuFix; stuCmdCnt.Format(L"SELECT COUNT(*)%s", stuBaseCmd.Chars()); CheckHr(GetOleDbCommand()->ExecCommand(stuCmdCnt.Bstr(), knSqlStmtSelectWithOneRowset)); CheckHr(GetOleDbCommand()->GetRowset(0)); CheckHr(GetOleDbCommand()->NextRow(&fMoreRows)); CheckHr(GetOleDbCommand()->GetColValue(1, reinterpret_cast <BYTE *>(&cRows), isizeof(hobj), &cbSpaceTaken, &fIsNull, 0)); stuCmd.Format(L"SELECT a.Id, a.Style%s", stuBaseCmd.Chars()); CheckHr(GetOleDbCommand()->ExecCommand(stuCmd.Bstr(), knSqlStmtSelectWithOneRowset)); CheckHr(GetOleDbCommand()->GetRowset(0)); CheckHr(GetOleDbCommand()->NextRow(&fMoreRows)); iRow = 0; while (fMoreRows) { CheckHr(GetOleDbCommand()->GetColValue(1, reinterpret_cast <BYTE *>(&hobj), isizeof(hobj), &cbSpaceTaken, &fIsNull, 0)); CheckHr(GetOleDbCommand()->GetColValue(2, reinterpret_cast <BYTE *>(*&rgch), isizeof(rgch), &cbSpaceTaken, &fIsNull, 0)); int cchw = cbSpaceTaken / isizeof(OLECHAR); StrUni stuOld(rgch, cchw); StrUni stuNew; if (Delete(stuOld)) { vstuFix.Push(L""); vhobjFix.Push(hobj); } else if (Rename(stuOld, stuNew)) { vstuFix.Push(stuNew); vhobjFix.Push(hobj); } CheckHr(GetOleDbCommand()->NextRow(&fMoreRows)); iRow++; SetPercentComplete((iRow * 50) / cRows); } SetPercentComplete(50); Assert(vhobjFix.Size() == vstuFix.Size()); ceFix = vstuFix.Size(); for (int ieFix = 0; ieFix < ceFix; ieFix++) { if (vstuFix[ieFix] == L"") { stuCmd.Format(L"UPDATE UserViewField SET Style = NULL where [Id] = '%d'", vhobjFix[ieFix]); } else { StrUtil::NormalizeStrUni(vstuFix[ieFix], UNORM_NFD); stuCmd.Format(L"UPDATE UserViewField SET Style = '%s' where [Id] = '%d'", vstuFix[ieFix].Chars(), vhobjFix[ieFix]); } CheckHr(GetOleDbCommand()->ExecCommand(stuCmd.Bstr(), knSqlStmtNoResults)); SetPercentComplete(50 + ((ieFix * 50) / ceFix)); } SetPercentComplete(100); CommitTrans(); Terminate(m_hvoRoot); if (m_qprog) m_qprog->DestroyHwnd(); END_COM_METHOD(g_fact, IID_IFwDbMergeStyles); }
// This test verifies that the slave run task label decorator can add // and remove labels from a task during the launch sequence. A task // with two labels ("foo":"bar" and "bar":"baz") is launched and will // get modified by the slave hook to strip the "foo":"bar" pair and // add a new "baz":"qux" pair. TEST_F(HookTest, VerifySlaveRunTaskHook) { Try<PID<Master>> master = StartMaster(); ASSERT_SOME(master); MockExecutor exec(DEFAULT_EXECUTOR_ID); TestContainerizer containerizer(&exec); Try<PID<Slave>> slave = StartSlave(&containerizer); ASSERT_SOME(slave); MockScheduler sched; MesosSchedulerDriver driver( &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL); EXPECT_CALL(sched, registered(&driver, _, _)); Future<vector<Offer>> offers; EXPECT_CALL(sched, resourceOffers(&driver, _)) .WillOnce(FutureArg<1>(&offers)) .WillRepeatedly(Return()); // Ignore subsequent offers. driver.start(); AWAIT_READY(offers); ASSERT_EQ(1u, offers.get().size()); TaskInfo task; task.set_name(""); task.mutable_task_id()->set_value("1"); task.mutable_slave_id()->CopyFrom(offers.get()[0].slave_id()); task.mutable_resources()->CopyFrom(offers.get()[0].resources()); task.mutable_executor()->CopyFrom(DEFAULT_EXECUTOR_INFO); // Add two labels: (1) will be removed by the hook to ensure that // runTaskHook can remove labels (2) will be preserved to ensure // that the framework can add labels to the task and have those be // available by the end of the launch task sequence when hooks are // used (to protect against hooks removing labels completely). Labels* labels = task.mutable_labels(); Label* label1 = labels->add_labels(); label1->set_key("foo"); label1->set_value("bar"); Label* label2 = labels->add_labels(); label2->set_key("bar"); label2->set_value("baz"); vector<TaskInfo> tasks; tasks.push_back(task); EXPECT_CALL(exec, registered(_, _, _, _)); Future<TaskInfo> taskInfo; EXPECT_CALL(exec, launchTask(_, _)) .WillOnce(DoAll( FutureArg<1>(&taskInfo), SendStatusUpdateFromTask(TASK_RUNNING))); driver.launchTasks(offers.get()[0].id(), tasks); AWAIT_READY(taskInfo); // The master hook will hang an extra label off. const Labels& labels_ = taskInfo.get().labels(); ASSERT_EQ(3, labels_.labels_size()); // The slave run task hook will prepend a new "baz":"qux" label. EXPECT_EQ(labels_.labels(0).key(), "baz"); EXPECT_EQ(labels_.labels(0).value(), "qux"); // Master launch task hook will still hang off test label. EXPECT_EQ(labels_.labels(1).key(), testLabelKey); EXPECT_EQ(labels_.labels(1).value(), testLabelValue); // And lastly, we only expect the "foo":"bar" pair to be stripped by // the module. The last pair should be the original "bar":"baz" // pair set by the test. EXPECT_EQ(labels_.labels(2).key(), "bar"); EXPECT_EQ(labels_.labels(2).value(), "baz"); driver.stop(); driver.join(); Shutdown(); // Must shutdown before 'containerizer' gets deallocated. }