static void Main(string[] args) { var data = new Data(); data.wireDecode(new Blob(TlvData)); // Use a hard-wired secret for testing. In a real application the signer // ensures that the verifier knows the shared key and its keyName. var key = new Blob(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }); if (KeyChain.verifyDataWithHmacWithSha256(data, key)) Console.Out.WriteLine("Hard-coded data signature verification: VERIFIED"); else Console.Out.WriteLine("Hard-coded data signature verification: FAILED"); var freshData = new Data(new Name("/ndn/abc")); var signature = new HmacWithSha256Signature(); signature.getKeyLocator().setType(KeyLocatorType.KEYNAME); signature.getKeyLocator().setKeyName(new Name("key1")); freshData.setSignature(signature); freshData.setContent(new Blob("SUCCESS!")); Console.Out.WriteLine("Signing fresh data packet " + freshData.getName().toUri()); KeyChain.signWithHmacWithSha256(freshData, key); if (KeyChain.verifyDataWithHmacWithSha256(freshData, key)) Console.Out.WriteLine("Freshly-signed data signature verification: VERIFIED"); else Console.Out.WriteLine("Freshly-signed data signature verification: FAILED"); }
public void onReceivedElement(ByteBuffer element) { LpPacket lpPacket = null; if (element.get(0) == net.named_data.jndn.encoding.tlv.Tlv.LpPacket_LpPacket) { // Decode the LpPacket and replace element with the fragment. lpPacket = new LpPacket(); // Set copy false so that the fragment is a slice which will be copied below. // The header fields are all integers and don't need to be copied. net.named_data.jndn.encoding.TlvWireFormat.get().decodeLpPacket(lpPacket, element, false); element = lpPacket.getFragmentWireEncoding().buf(); } // First, decode as Interest or Data. Interest interest = null; Data data = null; if (element.get(0) == net.named_data.jndn.encoding.tlv.Tlv.Interest || element.get(0) == net.named_data.jndn.encoding.tlv.Tlv.Data) { TlvDecoder decoder = new TlvDecoder(element); if (decoder.peekType(net.named_data.jndn.encoding.tlv.Tlv.Interest, element.remaining())) { interest = new Interest(); interest.wireDecode(element, net.named_data.jndn.encoding.TlvWireFormat.get()); if (lpPacket != null) { interest.setLpPacket(lpPacket); } } else if (decoder.peekType(net.named_data.jndn.encoding.tlv.Tlv.Data, element.remaining())) { data = new Data(); data.wireDecode(element, net.named_data.jndn.encoding.TlvWireFormat.get()); if (lpPacket != null) { data.setLpPacket(lpPacket); } } } if (lpPacket != null) { // We have decoded the fragment, so remove the wire encoding to save memory. lpPacket.setFragmentWireEncoding(new Blob()); NetworkNack networkNack = net.named_data.jndn.NetworkNack.getFirstHeader(lpPacket); if (networkNack != null) { if (interest == null) { // We got a Nack but not for an Interest, so drop the packet. return; } ArrayList <PendingInterestTable.Entry> pitEntries = new ArrayList <PendingInterestTable.Entry>(); pendingInterestTable_.extractEntriesForNackInterest(interest, pitEntries); for (int i = 0; i < pitEntries.Count; ++i) { PendingInterestTable.Entry pendingInterest = pitEntries[i]; try { pendingInterest.getOnNetworkNack().onNetworkNack( pendingInterest.getInterest(), networkNack); } catch (Exception ex) { logger_.log(ILOG.J2CsMapping.Util.Logging.Level.SEVERE, "Error in onNack", ex); } } // We have processed the network Nack packet. return; } } // Now process as Interest or Data. if (interest != null) { dispatchInterest(interest); } else if (data != null) { satisfyPendingInterests(data); } }
public void testGenericSignature() { // Test correct encoding. GenericSignature signature = new GenericSignature(); signature.setSignatureInfoEncoding(new Blob(experimentalSignatureInfo, false), -1); Blob signatureValue = new Blob(toBuffer(new int[] { 1, 2, 3, 4 }), false); signature.setSignature(signatureValue); freshData.setSignature(signature); Blob encoding = freshData.wireEncode(); Data decodedData = new Data(); try { decodedData.wireDecode(encoding); } catch (EncodingException ex) { Assert.Fail("Error decoding Data with GenericSignature: " + ex); } GenericSignature decodedSignature = (GenericSignature) decodedData .getSignature(); Assert.AssertEquals(experimentalSignatureType, decodedSignature.getTypeCode()); Assert.AssertTrue(new Blob(experimentalSignatureInfo, false) .equals(decodedSignature.getSignatureInfoEncoding())); Assert.AssertTrue(signatureValue.equals(decodedSignature.getSignature())); // Test bad encoding. signature = new GenericSignature(); signature.setSignatureInfoEncoding(new Blob( experimentalSignatureInfoNoSignatureType, false), -1); signature.setSignature(signatureValue); freshData.setSignature(signature); bool gotError = true; try { freshData.wireEncode(); gotError = false; } catch (Exception ex_0) { } if (!gotError) Assert.Fail("Expected encoding error for experimentalSignatureInfoNoSignatureType"); signature = new GenericSignature(); signature.setSignatureInfoEncoding(new Blob( experimentalSignatureInfoBadTlv, false), -1); signature.setSignature(signatureValue); freshData.setSignature(signature); gotError = true; try { freshData.wireEncode(); gotError = false; } catch (Exception ex_1) { } if (!gotError) Assert.Fail("Expected encoding error for experimentalSignatureInfoBadTlv"); }
public void testFullName() { Data data = new Data(); try { data.wireDecode(codedData); } catch (EncodingException ex) { Assert.Fail("Can't decode codedData"); } // Check the full name format. Assert.AssertEquals(data.getName().size() + 1, data.getFullName().size()); Assert.AssertEquals(data.getName(), data.getFullName().getPrefix(-1)); Assert.AssertEquals(32, data.getFullName().get(-1).getValue().size()); // Check the independent digest calculation. Blob newDigest = new Blob(net.named_data.jndn.util.Common.digestSha256(codedData)); Assert.AssertTrue(newDigest.equals(data.getFullName().get(-1).getValue())); // Check the expected URI. Assert.AssertEquals( "/ndn/abc/sha256digest=" + "96556d685dcb1af04be4ae57f0e7223457d4055ea9b3d07c0d337bef4a8b3ee9", data.getFullName().toUri()); // Changing the Data packet should change the full name. Name saveFullName = new Name(data.getFullName()); data.setContent(new Blob()); Assert.AssertFalse(data.getFullName().get(-1).equals(saveFullName.get(-1))); }
public void testEncodeDecode() { Data data = new Data(); try { data.wireDecode(codedData); } catch (EncodingException ex) { Assert.Fail("Can't decode codedData"); } // Set the content again to clear the cached encoding so we encode again. data.setContent(data.getContent()); Blob encoding = data.wireEncode(); Data reDecodedData = new Data(); try { reDecodedData.wireDecode(encoding); } catch (EncodingException ex_0) { Assert.Fail("Can't decode reDecodedData"); } Assert.AssertArrayEquals("Re-decoded data does not match original dump", ILOG.J2CsMapping.Collections.Collections.ToArray(initialDump), ILOG.J2CsMapping.Collections.Collections.ToArray(dumpData(reDecodedData))); }
public void testDump() { Data data = new Data(); try { data.wireDecode(codedData); } catch (EncodingException ex) { Assert.Fail("Can't decode codedData"); } Assert.AssertArrayEquals("Initial dump does not have expected format", ILOG.J2CsMapping.Collections.Collections.ToArray(dumpData(data)), ILOG.J2CsMapping.Collections.Collections.ToArray(initialDump)); }
public void testConstruction() { // Debug: This should be a Certificate. Data certificate = new Data(); certificate.wireDecode(new Blob(CERT, false)); // TODO: Finish tests. }
/** * Loop to decode a data packet nIterations times. * @param nIterations The number of iterations. * @param useCrypto If true, verify the signature. If false, don't verify. * @param keyType KeyType.RSA or EC, used if useCrypto is true. * @param encoding The wire encoding to decode. * @return The number of seconds for all iterations. * @throws EncodingException */ private static double benchmarkDecodeDataSeconds(int nIterations, bool useCrypto, KeyType keyType, Blob encoding) { // Initialize the KeyChain storage in case useCrypto is true. MemoryIdentityStorage identityStorage = new MemoryIdentityStorage(); KeyChain keyChain = new KeyChain (new IdentityManager(identityStorage, new MemoryPrivateKeyStorage()), new SelfVerifyPolicyManager(identityStorage)); Name keyName = new Name("/testname/DSK-123"); Name certificateName = keyName.getSubName(0, keyName.size() - 1).append ("KEY").append(keyName.get(-1)).append("ID-CERT").append("0"); identityStorage.addKey(keyName, KeyType.RSA, new Blob(DEFAULT_RSA_PUBLIC_KEY_DER)); VerifyCallbacks callbacks = new VerifyCallbacks(); double start = getNowSeconds(); for (int i = 0; i < nIterations; ++i) { Data data = new Data(); data.wireDecode(encoding.buf()); if (useCrypto) keyChain.verifyData(data, callbacks, callbacks); } double finish = getNowSeconds(); return finish - start; }
public void onReceivedElement(ByteBuffer element) { LpPacket lpPacket = null; if (element.get(0) == net.named_data.jndn.encoding.tlv.Tlv.LpPacket_LpPacket) { // Decode the LpPacket and replace element with the fragment. lpPacket = new LpPacket(); // Set copy false so that the fragment is a slice which will be copied below. // The header fields are all integers and don't need to be copied. net.named_data.jndn.encoding.TlvWireFormat.get().decodeLpPacket(lpPacket, element, false); element = lpPacket.getFragmentWireEncoding().buf(); } // First, decode as Interest or Data. Interest interest = null; Data data = null; if (element.get(0) == net.named_data.jndn.encoding.tlv.Tlv.Interest || element.get(0) == net.named_data.jndn.encoding.tlv.Tlv.Data) { TlvDecoder decoder = new TlvDecoder(element); if (decoder.peekType(net.named_data.jndn.encoding.tlv.Tlv.Interest, element.remaining())) { interest = new Interest(); interest.wireDecode(element, net.named_data.jndn.encoding.TlvWireFormat.get()); if (lpPacket != null) interest.setLpPacket(lpPacket); } else if (decoder.peekType(net.named_data.jndn.encoding.tlv.Tlv.Data, element.remaining())) { data = new Data(); data.wireDecode(element, net.named_data.jndn.encoding.TlvWireFormat.get()); if (lpPacket != null) data.setLpPacket(lpPacket); } } if (lpPacket != null) { // We have decoded the fragment, so remove the wire encoding to save memory. lpPacket.setFragmentWireEncoding(new Blob()); NetworkNack networkNack = net.named_data.jndn.NetworkNack.getFirstHeader(lpPacket); if (networkNack != null) { if (interest == null) // We got a Nack but not for an Interest, so drop the packet. return; ArrayList<PendingInterestTable.Entry> pitEntries = new ArrayList<PendingInterestTable.Entry>(); pendingInterestTable_.extractEntriesForNackInterest(interest, pitEntries); for (int i = 0; i < pitEntries.Count; ++i) { PendingInterestTable.Entry pendingInterest = pitEntries[i]; try { pendingInterest.getOnNetworkNack().onNetworkNack( pendingInterest.getInterest(), networkNack); } catch (Exception ex) { logger_.log(ILOG.J2CsMapping.Util.Logging.Level.SEVERE, "Error in onNack", ex); } } // We have processed the network Nack packet. return; } } // Now process as Interest or Data. if (interest != null) { // Quickly lock and get all interest filter callbacks which match. ArrayList matchedFilters = new ArrayList(); interestFilterTable_.getMatchedFilters(interest, matchedFilters); // The lock on interestFilterTable_ is released, so call the callbacks. for (int i_0 = 0; i_0 < matchedFilters.Count; ++i_0) { InterestFilterTable.Entry entry = (InterestFilterTable.Entry) matchedFilters[i_0]; try { entry.getOnInterest().onInterest( entry.getFilter().getPrefix(), interest, entry.getFace(), entry.getInterestFilterId(), entry.getFilter()); } catch (Exception ex_1) { logger_.log(ILOG.J2CsMapping.Util.Logging.Level.SEVERE, "Error in onInterest", ex_1); } } } else if (data != null) { ArrayList<PendingInterestTable.Entry> pitEntries_2 = new ArrayList<PendingInterestTable.Entry>(); pendingInterestTable_.extractEntriesForExpressedInterest(data, pitEntries_2); for (int i_3 = 0; i_3 < pitEntries_2.Count; ++i_3) { PendingInterestTable.Entry pendingInterest_4 = pitEntries_2[i_3]; try { pendingInterest_4.getOnData().onData( pendingInterest_4.getInterest(), data); } catch (Exception ex_5) { logger_.log(ILOG.J2CsMapping.Util.Logging.Level.SEVERE, "Error in onData", ex_5); } } } }
static void Main(string[] args) { var data = new Data(); data.wireDecode(new Blob(TlvData)); Console.Out.WriteLine("Decoded Data:"); dumpData(data); // Set the content again to clear the cached encoding so we encode again. data.setContent(data.getContent()); var encoding = data.wireEncode(); var reDecodedData = new Data(); reDecodedData.wireDecode(encoding); Console.Out.WriteLine(""); Console.Out.WriteLine("Re-decoded Data:"); dumpData(reDecodedData); var identityStorage = new MemoryIdentityStorage(); var privateKeyStorage = new MemoryPrivateKeyStorage(); var keyChain = new KeyChain (new IdentityManager(identityStorage, privateKeyStorage), new SelfVerifyPolicyManager(identityStorage)); // Initialize the storage. var keyName = new Name("/testname/DSK-123"); var certificateName = keyName.getSubName(0, keyName.size() - 1).append ("KEY").append(keyName.get(-1)).append("ID-CERT").append("0"); identityStorage.addKey(keyName, KeyType.RSA, new Blob(DEFAULT_RSA_PUBLIC_KEY_DER)); privateKeyStorage.setKeyPairForKeyName (keyName, KeyType.RSA, new ByteBuffer(DEFAULT_RSA_PUBLIC_KEY_DER), new ByteBuffer(DEFAULT_RSA_PRIVATE_KEY_DER)); VerifyCallbacks callbacks = new VerifyCallbacks("Re-decoded Data"); keyChain.verifyData(reDecodedData, callbacks, callbacks); var freshData = new Data(new Name("/ndn/abc")); freshData.setContent(new Blob("SUCCESS!")); freshData.getMetaInfo().setFreshnessPeriod(5000); freshData.getMetaInfo().setFinalBlockId(new Name("/%00%09").get(0)); keyChain.sign(freshData, certificateName); Console.Out.WriteLine(""); Console.Out.WriteLine("Freshly-signed Data:"); dumpData(freshData); callbacks = new VerifyCallbacks("Freshly-signed Data"); keyChain.verifyData(freshData, callbacks, callbacks); }
public void onReceivedElement(ByteBuffer element) { LpPacket lpPacket = null; if (element.get(0) == net.named_data.jndn.encoding.tlv.Tlv.LpPacket_LpPacket) { // Decode the LpPacket and replace element with the fragment. lpPacket = new LpPacket(); net.named_data.jndn.encoding.TlvWireFormat.get().decodeLpPacket(lpPacket, element); element = lpPacket.getFragmentWireEncoding().buf(); } // First, decode as Interest or Data. Interest interest = null; Data data = null; if (element.get(0) == net.named_data.jndn.encoding.tlv.Tlv.Interest || element.get(0) == net.named_data.jndn.encoding.tlv.Tlv.Data) { TlvDecoder decoder = new TlvDecoder(element); if (decoder.peekType(net.named_data.jndn.encoding.tlv.Tlv.Interest, element.remaining())) { interest = new Interest(); interest.wireDecode(element, net.named_data.jndn.encoding.TlvWireFormat.get()); if (lpPacket != null) { interest.setLpPacket(lpPacket); } } else if (decoder.peekType(net.named_data.jndn.encoding.tlv.Tlv.Data, element.remaining())) { data = new Data(); data.wireDecode(element, net.named_data.jndn.encoding.TlvWireFormat.get()); if (lpPacket != null) { data.setLpPacket(lpPacket); } } } if (lpPacket != null) { // We have decoded the fragment, so remove the wire encoding to save memory. lpPacket.setFragmentWireEncoding(new Blob()); NetworkNack networkNack = net.named_data.jndn.NetworkNack.getFirstHeader(lpPacket); if (networkNack != null) { if (interest == null) { // We got a Nack but not for an Interest, so drop the packet. return; } ArrayList <PendingInterestTable.Entry> pitEntries = new ArrayList <PendingInterestTable.Entry>(); pendingInterestTable_.extractEntriesForNackInterest(interest, pitEntries); for (int i = 0; i < pitEntries.Count; ++i) { PendingInterestTable.Entry pendingInterest = pitEntries[i]; try { pendingInterest.getOnNetworkNack().onNetworkNack( pendingInterest.getInterest(), networkNack); } catch (Exception ex) { logger_.log(ILOG.J2CsMapping.Util.Logging.Level.SEVERE, "Error in onNack", ex); } } // We have process the network Nack packet. return; } } // Now process as Interest or Data. if (interest != null) { // Quickly lock and get all interest filter callbacks which match. ArrayList matchedFilters = new ArrayList(); interestFilterTable_.getMatchedFilters(interest, matchedFilters); // The lock on interestFilterTable_ is released, so call the callbacks. for (int i_0 = 0; i_0 < matchedFilters.Count; ++i_0) { InterestFilterTable.Entry entry = (InterestFilterTable.Entry)matchedFilters[i_0]; try { entry.getOnInterest().onInterest( entry.getFilter().getPrefix(), interest, entry.getFace(), entry.getInterestFilterId(), entry.getFilter()); } catch (Exception ex_1) { logger_.log(ILOG.J2CsMapping.Util.Logging.Level.SEVERE, "Error in onInterest", ex_1); } } } else if (data != null) { ArrayList <PendingInterestTable.Entry> pitEntries_2 = new ArrayList <PendingInterestTable.Entry>(); pendingInterestTable_.extractEntriesForExpressedInterest( data.getName(), pitEntries_2); for (int i_3 = 0; i_3 < pitEntries_2.Count; ++i_3) { PendingInterestTable.Entry pendingInterest_4 = pitEntries_2[i_3]; try { pendingInterest_4.getOnData().onData( pendingInterest_4.getInterest(), data); } catch (Exception ex_5) { logger_.log(ILOG.J2CsMapping.Util.Logging.Level.SEVERE, "Error in onData", ex_5); } } } }
public void testRefresh10s() { StringBuilder encodedData = new StringBuilder(); TextReader dataFile = new System.IO.StreamReader(new FileInfo(System.IO.Path.Combine(policyConfigDirectory_.FullName,"testData")).OpenWrite()); // Use "try/finally instead of "try-with-resources" or "using" // which are not supported before Java 7. try { String line; while ((line = dataFile.readLine()) != null) encodedData.append(line); } finally { dataFile.close(); } byte[] decodedData = net.named_data.jndn.util.Common.base64Decode(encodedData.toString()); Data data = new Data(); data.wireDecode(new Blob(decodedData, false)); // This test is needed, since the KeyChain will express interests in unknown // certificates. VerificationResult vr = doVerify(policyManager_, data); AssertTrue( "ConfigPolicyManager did not create ValidationRequest for unknown certificate", vr.hasFurtherSteps_); AssertEquals( "ConfigPolicyManager called success callback with pending ValidationRequest", 0, vr.successCount_); AssertEquals( "ConfigPolicyManager called failure callback with pending ValidationRequest", 0, vr.failureCount_); // Now save the cert data to our anchor directory, and wait. // We have to sign it with the current identity or the policy manager will // create an interest for the signing certificate. IdentityCertificate cert = new IdentityCertificate(); byte[] certData = net.named_data.jndn.util.Common.base64Decode(CERT_DUMP); cert.wireDecode(new Blob(certData, false)); keyChain_.signByIdentity(cert, identityName_); Blob signedCertBlob = cert.wireEncode(); String encodedCert = net.named_data.jndn.util.Common.base64Encode(signedCertBlob .getImmutableArray()); BufferedStream certFile = new BufferedStream(new System.IO.StreamWriter(testCertFile_.OpenRead())); try { certFile.Write(encodedCert,0,encodedCert.Substring(0,encodedCert.Length)); certFile.flush(); } finally { certFile.close(); } // Still too early for refresh to pick it up. vr = doVerify(policyManager_, data); AssertTrue("ConfigPolicyManager refresh occured sooner than specified", vr.hasFurtherSteps_); AssertEquals( "ConfigPolicyManager called success callback with pending ValidationRequest", 0, vr.successCount_); AssertEquals( "ConfigPolicyManager called failure callback with pending ValidationRequest", 0, vr.failureCount_); ILOG.J2CsMapping.Threading.ThreadWrapper.sleep(6000); // Now we should find it. vr = doVerify(policyManager_, data); AssertFalse("ConfigPolicyManager did not refresh certificate store", vr.hasFurtherSteps_); AssertEquals("Verification success called " + vr.successCount_ + " times instead of 1", 1, vr.successCount_); AssertEquals("ConfigPolicyManager did not verify valid signed data", 0, vr.failureCount_); }
internal void setManager(GroupManager manager) { // Set up the first schedule. Schedule schedule1 = new Schedule(); RepetitiveInterval interval11 = new RepetitiveInterval( net.named_data.jndn.tests.unit_tests.UnitTestsCommon.fromIsoString("20150825T000000"), net.named_data.jndn.tests.unit_tests.UnitTestsCommon.fromIsoString("20150827T000000"), 5, 10, 2, net.named_data.jndn.encrypt.RepetitiveInterval.RepeatUnit.DAY); RepetitiveInterval interval12 = new RepetitiveInterval( net.named_data.jndn.tests.unit_tests.UnitTestsCommon.fromIsoString("20150825T000000"), net.named_data.jndn.tests.unit_tests.UnitTestsCommon.fromIsoString("20150827T000000"), 6, 8, 1, net.named_data.jndn.encrypt.RepetitiveInterval.RepeatUnit.DAY); RepetitiveInterval interval13 = new RepetitiveInterval( net.named_data.jndn.tests.unit_tests.UnitTestsCommon.fromIsoString("20150827T000000"), net.named_data.jndn.tests.unit_tests.UnitTestsCommon.fromIsoString("20150827T000000"), 7, 8); schedule1.addWhiteInterval(interval11); schedule1.addWhiteInterval(interval12); schedule1.addBlackInterval(interval13); // Set up the second schedule. Schedule schedule2 = new Schedule(); RepetitiveInterval interval21 = new RepetitiveInterval( net.named_data.jndn.tests.unit_tests.UnitTestsCommon.fromIsoString("20150825T000000"), net.named_data.jndn.tests.unit_tests.UnitTestsCommon.fromIsoString("20150827T000000"), 9, 12, 1, net.named_data.jndn.encrypt.RepetitiveInterval.RepeatUnit.DAY); RepetitiveInterval interval22 = new RepetitiveInterval( net.named_data.jndn.tests.unit_tests.UnitTestsCommon.fromIsoString("20150827T000000"), net.named_data.jndn.tests.unit_tests.UnitTestsCommon.fromIsoString("20150827T000000"), 6, 8); RepetitiveInterval interval23 = new RepetitiveInterval( net.named_data.jndn.tests.unit_tests.UnitTestsCommon.fromIsoString("20150827T000000"), net.named_data.jndn.tests.unit_tests.UnitTestsCommon.fromIsoString("20150827T000000"), 2, 4); schedule2.addWhiteInterval(interval21); schedule2.addWhiteInterval(interval22); schedule2.addBlackInterval(interval23); // Add them to the group manager database. manager.addSchedule("schedule1", schedule1); manager.addSchedule("schedule2", schedule2); // Make some adaptions to certificate. Blob dataBlob = certificate.wireEncode(); Data memberA = new Data(); memberA.wireDecode(dataBlob, net.named_data.jndn.encoding.TlvWireFormat.get()); memberA.setName(new Name("/ndn/memberA/KEY/ksk-123/ID-CERT/123")); Data memberB = new Data(); memberB.wireDecode(dataBlob, net.named_data.jndn.encoding.TlvWireFormat.get()); memberB.setName(new Name("/ndn/memberB/KEY/ksk-123/ID-CERT/123")); Data memberC = new Data(); memberC.wireDecode(dataBlob, net.named_data.jndn.encoding.TlvWireFormat.get()); memberC.setName(new Name("/ndn/memberC/KEY/ksk-123/ID-CERT/123")); // Add the members to the database. manager.addMember("schedule1", memberA); manager.addMember("schedule1", memberB); manager.addMember("schedule2", memberC); }